Initial checkin of COMROGUE source after having gotten initial memory map right
This commit is contained in:
commit
5b93e58fb3
32
COPYRIGHT
Normal file
32
COPYRIGHT
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
The COMROGUE Operating System for Raspberry Pi
|
||||||
|
|
||||||
|
Copyright (c) 2013, Eric J. Bowersox / Erbosoft Enterprises
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
This program is free for commercial and non-commercial use as long as the following conditions are
|
||||||
|
adhered to.
|
||||||
|
|
||||||
|
Copyright in this file remains Eric J. Bowersox and/or Erbosoft, and as such any copyright notices
|
||||||
|
in the code are not to be removed.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without modification, are permitted
|
||||||
|
provided that the following conditions are met:
|
||||||
|
|
||||||
|
* Redistributions of source code must retain the above copyright notice, this list of conditions and
|
||||||
|
the following disclaimer.
|
||||||
|
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
|
||||||
|
the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
|
||||||
|
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||||
|
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||||
|
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
Some files in the source have been obtained primarily from other sources, modified or not. Where applicable,
|
||||||
|
the original copyright headers remain in those source files.
|
||||||
|
|
||||||
|
"Raspberry Pi" is a trademark of the Raspberry Pi Foundation.
|
53
Makefile
Normal file
53
Makefile
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
#
|
||||||
|
# This file is part of the COMROGUE Operating System for Raspberry Pi
|
||||||
|
#
|
||||||
|
# Copyright (c) 2013, Eric J. Bowersox / Erbosoft Enterprises
|
||||||
|
# All rights reserved.
|
||||||
|
#
|
||||||
|
# This program is free for commercial and non-commercial use as long as the following conditions are
|
||||||
|
# adhered to.
|
||||||
|
#
|
||||||
|
# Copyright in this file remains Eric J. Bowersox and/or Erbosoft, and as such any copyright notices
|
||||||
|
# in the code are not to be removed.
|
||||||
|
#
|
||||||
|
# Redistribution and use in source and binary forms, with or without modification, are permitted
|
||||||
|
# provided that the following conditions are met:
|
||||||
|
#
|
||||||
|
# * Redistributions of source code must retain the above copyright notice, this list of conditions and
|
||||||
|
# the following disclaimer.
|
||||||
|
# * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
|
||||||
|
# the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||||
|
#
|
||||||
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
|
||||||
|
# WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||||
|
# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||||
|
# TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
# POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
#
|
||||||
|
# "Raspberry Pi" is a trademark of the Raspberry Pi Foundation.
|
||||||
|
|
||||||
|
MAKEFLAGS += -rR
|
||||||
|
|
||||||
|
all: tools idl kernel
|
||||||
|
|
||||||
|
tools:
|
||||||
|
make -C tools
|
||||||
|
|
||||||
|
idl:
|
||||||
|
make -C idl
|
||||||
|
|
||||||
|
kernel:
|
||||||
|
make -C kernel
|
||||||
|
|
||||||
|
clean:
|
||||||
|
make -C tools clean
|
||||||
|
make -C idl clean
|
||||||
|
make -C kernel clean
|
||||||
|
|
||||||
|
cleanbackup:
|
||||||
|
find . -name '*~' -delete
|
||||||
|
|
||||||
|
.PHONY: tools idl kernel
|
31
documentation/license_headers/license_header.S
Normal file
31
documentation/license_headers/license_header.S
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
/*
|
||||||
|
* This file is part of the COMROGUE Operating System for Raspberry Pi
|
||||||
|
*
|
||||||
|
* Copyright (c) 2013, Eric J. Bowersox / Erbosoft Enterprises
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This program is free for commercial and non-commercial use as long as the following conditions are
|
||||||
|
* adhered to.
|
||||||
|
*
|
||||||
|
* Copyright in this file remains Eric J. Bowersox and/or Erbosoft, and as such any copyright notices
|
||||||
|
* in the code are not to be removed.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification, are permitted
|
||||||
|
* provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* * Redistributions of source code must retain the above copyright notice, this list of conditions and
|
||||||
|
* the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
|
||||||
|
* the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
|
||||||
|
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||||
|
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||||
|
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* "Raspberry Pi" is a trademark of the Raspberry Pi Foundation.
|
||||||
|
*/
|
31
documentation/license_headers/license_header.c
Normal file
31
documentation/license_headers/license_header.c
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
/*
|
||||||
|
* This file is part of the COMROGUE Operating System for Raspberry Pi
|
||||||
|
*
|
||||||
|
* Copyright (c) 2013, Eric J. Bowersox / Erbosoft Enterprises
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This program is free for commercial and non-commercial use as long as the following conditions are
|
||||||
|
* adhered to.
|
||||||
|
*
|
||||||
|
* Copyright in this file remains Eric J. Bowersox and/or Erbosoft, and as such any copyright notices
|
||||||
|
* in the code are not to be removed.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification, are permitted
|
||||||
|
* provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* * Redistributions of source code must retain the above copyright notice, this list of conditions and
|
||||||
|
* the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
|
||||||
|
* the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
|
||||||
|
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||||
|
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||||
|
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* "Raspberry Pi" is a trademark of the Raspberry Pi Foundation.
|
||||||
|
*/
|
31
documentation/license_headers/license_header.idl
Normal file
31
documentation/license_headers/license_header.idl
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
/*
|
||||||
|
* This file is part of the COMROGUE Operating System for Raspberry Pi
|
||||||
|
*
|
||||||
|
* Copyright (c) 2013, Eric J. Bowersox / Erbosoft Enterprises
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This program is free for commercial and non-commercial use as long as the following conditions are
|
||||||
|
* adhered to.
|
||||||
|
*
|
||||||
|
* Copyright in this file remains Eric J. Bowersox and/or Erbosoft, and as such any copyright notices
|
||||||
|
* in the code are not to be removed.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification, are permitted
|
||||||
|
* provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* * Redistributions of source code must retain the above copyright notice, this list of conditions and
|
||||||
|
* the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
|
||||||
|
* the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
|
||||||
|
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||||
|
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||||
|
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* "Raspberry Pi" is a trademark of the Raspberry Pi Foundation.
|
||||||
|
*/
|
31
documentation/license_headers/license_header.lds
Normal file
31
documentation/license_headers/license_header.lds
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
/*
|
||||||
|
* This file is part of the COMROGUE Operating System for Raspberry Pi
|
||||||
|
*
|
||||||
|
* Copyright (c) 2013, Eric J. Bowersox / Erbosoft Enterprises
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This program is free for commercial and non-commercial use as long as the following conditions are
|
||||||
|
* adhered to.
|
||||||
|
*
|
||||||
|
* Copyright in this file remains Eric J. Bowersox and/or Erbosoft, and as such any copyright notices
|
||||||
|
* in the code are not to be removed.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification, are permitted
|
||||||
|
* provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* * Redistributions of source code must retain the above copyright notice, this list of conditions and
|
||||||
|
* the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
|
||||||
|
* the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
|
||||||
|
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||||
|
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||||
|
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* "Raspberry Pi" is a trademark of the Raspberry Pi Foundation.
|
||||||
|
*/
|
30
documentation/license_headers/license_header.makefile
Normal file
30
documentation/license_headers/license_header.makefile
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
#
|
||||||
|
# This file is part of the COMROGUE Operating System for Raspberry Pi
|
||||||
|
#
|
||||||
|
# Copyright (c) 2013, Eric J. Bowersox / Erbosoft Enterprises
|
||||||
|
# All rights reserved.
|
||||||
|
#
|
||||||
|
# This program is free for commercial and non-commercial use as long as the following conditions are
|
||||||
|
# adhered to.
|
||||||
|
#
|
||||||
|
# Copyright in this file remains Eric J. Bowersox and/or Erbosoft, and as such any copyright notices
|
||||||
|
# in the code are not to be removed.
|
||||||
|
#
|
||||||
|
# Redistribution and use in source and binary forms, with or without modification, are permitted
|
||||||
|
# provided that the following conditions are met:
|
||||||
|
#
|
||||||
|
# * Redistributions of source code must retain the above copyright notice, this list of conditions and
|
||||||
|
# the following disclaimer.
|
||||||
|
# * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
|
||||||
|
# the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||||
|
#
|
||||||
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
|
||||||
|
# WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||||
|
# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||||
|
# TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
# POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
#
|
||||||
|
# "Raspberry Pi" is a trademark of the Raspberry Pi Foundation.
|
9
documentation/sample-atags-info.txt
Normal file
9
documentation/sample-atags-info.txt
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
--- COMROGUE 0.00
|
||||||
|
- KiSystemStartup
|
||||||
|
ATAG @ c0000100: 54410001[5]
|
||||||
|
- flags = 00000000, pgsiz = 0, root = 0
|
||||||
|
ATAG @ c0000114: 54410002[4]
|
||||||
|
- memory: 469762048 bytes at physaddr 00000000
|
||||||
|
ATAG @ c0000124: 54410009[95]
|
||||||
|
- cmdline: "dma.dmachans=0x7f35 bcm2708_fb.fbwidth=1360 bcm2708_fb.fbheight=768 bcm2708.boardrev=0xf bcm2708.serial=0x3368e8ee smsc95xx.macaddr=B8:27:EB:68:E8:EE sdhci-bcm2708.emmc_clock_freq=100000000 vc_mem.mem_base=0x1ec00000 vc_mem.mem_size=0x20000000 dwc_otg.lpm_enable=0 console=ttyAMA0,115200 kgdboc=ttyAMA0,115200 console=tty1 root=/dev/mmcblk0p2 rootfstype=ext4 rootwait"
|
||||||
|
ATAG @ c00002a0: 00000000[0]
|
23
documentation/sample-startup-info.txt
Normal file
23
documentation/sample-startup-info.txt
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
COMROGUEPrestart
|
||||||
|
EMmInit: TTB1@00010000
|
||||||
|
Map 00000000->00000000,cpg=0000000A,tf=00000001,pf=00000012
|
||||||
|
Map 20000000->20000000,cpg=00000400,tf=00000001,pf=00000012
|
||||||
|
Map 0000A000->B0000000,cpg=00000002,tf=00000001,pf=0000002E
|
||||||
|
Map 0000C000->C0000000,cpg=00000001,tf=00000001,pf=0000001E
|
||||||
|
Map 0000D000->C0001000,cpg=00000000,tf=00000001,pf=0000001F
|
||||||
|
Map 0000D000->C0001000,cpg=00000001,tf=00000001,pf=0000001E
|
||||||
|
Map 0000E000->C0002000,cpg=00000002,tf=00000001,pf=0000001F
|
||||||
|
Map 00010000->C0004000,cpg=00000004,tf=00000001,pf=0000001F
|
||||||
|
Map 00014000->C0008000,cpg=00000080,tf=00000001,pf=0000001F
|
||||||
|
Map 20000000->E0000000,cpg=00000400,tf=00000001,pf=00000012
|
||||||
|
--- COMROGUE 0.00
|
||||||
|
- KiSystemStartup
|
||||||
|
Mach type c42, revision f, serial 3368e8ee
|
||||||
|
Memory: 131072 total pages (114688 available), 0 TTB gap
|
||||||
|
TTB1 @ PA 00010000, VMA C0004000
|
||||||
|
MPDB @ PA 00014000, VMA C0008000, 128 pages
|
||||||
|
Page tables @ PA 00094000, 2 pages, 1 free on last one
|
||||||
|
First free PA = 00096000, first free VMA = C0088000
|
||||||
|
EMMC clock freq = 100000000
|
||||||
|
VC memory is at PHYS:1EC00000, 536870912 bytes, framebuffer 1360x768
|
||||||
|
MAC address B8:27:EB:68:E8:EE
|
45
idl/Makefile
Normal file
45
idl/Makefile
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
#
|
||||||
|
# This file is part of the COMROGUE Operating System for Raspberry Pi
|
||||||
|
#
|
||||||
|
# Copyright (c) 2013, Eric J. Bowersox / Erbosoft Enterprises
|
||||||
|
# All rights reserved.
|
||||||
|
#
|
||||||
|
# This program is free for commercial and non-commercial use as long as the following conditions are
|
||||||
|
# adhered to.
|
||||||
|
#
|
||||||
|
# Copyright in this file remains Eric J. Bowersox and/or Erbosoft, and as such any copyright notices
|
||||||
|
# in the code are not to be removed.
|
||||||
|
#
|
||||||
|
# Redistribution and use in source and binary forms, with or without modification, are permitted
|
||||||
|
# provided that the following conditions are met:
|
||||||
|
#
|
||||||
|
# * Redistributions of source code must retain the above copyright notice, this list of conditions and
|
||||||
|
# the following disclaimer.
|
||||||
|
# * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
|
||||||
|
# the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||||
|
#
|
||||||
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
|
||||||
|
# WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||||
|
# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||||
|
# TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
# POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
#
|
||||||
|
# "Raspberry Pi" is a trademark of the Raspberry Pi Foundation.
|
||||||
|
|
||||||
|
MAKEFLAGS += -rR
|
||||||
|
|
||||||
|
PIDL = ../tools/pidl/pidl
|
||||||
|
|
||||||
|
IDL_FILES := $(wildcard comrogue/*.idl)
|
||||||
|
H_FILES := $(subst .idl,.h,${IDL_FILES})
|
||||||
|
|
||||||
|
all: ${H_FILES}
|
||||||
|
|
||||||
|
%.h: %.idl
|
||||||
|
${PIDL} --includedir . --comrogue-header=$@ -- $<
|
||||||
|
|
||||||
|
clean:
|
||||||
|
-rm comrogue/*.h
|
106
idl/comrogue/object_types.idl
Normal file
106
idl/comrogue/object_types.idl
Normal file
|
@ -0,0 +1,106 @@
|
||||||
|
/*
|
||||||
|
* This file is part of the COMROGUE Operating System for Raspberry Pi
|
||||||
|
*
|
||||||
|
* Copyright (c) 2013, Eric J. Bowersox / Erbosoft Enterprises
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This program is free for commercial and non-commercial use as long as the following conditions are
|
||||||
|
* adhered to.
|
||||||
|
*
|
||||||
|
* Copyright in this file remains Eric J. Bowersox and/or Erbosoft, and as such any copyright notices
|
||||||
|
* in the code are not to be removed.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification, are permitted
|
||||||
|
* provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* * Redistributions of source code must retain the above copyright notice, this list of conditions and
|
||||||
|
* the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
|
||||||
|
* the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
|
||||||
|
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||||
|
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||||
|
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* "Raspberry Pi" is a trademark of the Raspberry Pi Foundation.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*---------------------------------------------------------
|
||||||
|
* Standard data type declarations for COMROGUE interfaces
|
||||||
|
*---------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
[uuid(b381db2c-471e-4288-ba62-878be5ceb393), version(0.1), pointer_default(unique)]
|
||||||
|
interface ICOMROGUETypes
|
||||||
|
{
|
||||||
|
/* Integral type definitions */
|
||||||
|
typedef int16 INT16;
|
||||||
|
typedef uint16 UINT16;
|
||||||
|
typedef int32 INT32;
|
||||||
|
typedef uint32 UINT32;
|
||||||
|
typedef dlong INT64;
|
||||||
|
typedef udlong UINT64;
|
||||||
|
|
||||||
|
typedef INT32 INT_PTR;
|
||||||
|
typedef UINT32 UINT_PTR;
|
||||||
|
|
||||||
|
/* Base pointer type definitions */
|
||||||
|
typedef INT16 *PINT16;
|
||||||
|
typedef UINT16 *PUINT16;
|
||||||
|
typedef INT32 *PINT32;
|
||||||
|
typedef UINT32 *PUINT32;
|
||||||
|
typedef INT64 *PINT64;
|
||||||
|
typedef UINT64 *PUINT64;
|
||||||
|
typedef void *PVOID;
|
||||||
|
typedef const void *PCVOID;
|
||||||
|
|
||||||
|
/* Pointer-to-pointer definitions */
|
||||||
|
typedef PVOID *PPVOID;
|
||||||
|
|
||||||
|
/* Character types */
|
||||||
|
typedef char CHAR;
|
||||||
|
typedef uint8 UCHAR;
|
||||||
|
typedef uint8 BYTE;
|
||||||
|
|
||||||
|
typedef CHAR *PCHAR;
|
||||||
|
typedef const CHAR *PCCHAR;
|
||||||
|
typedef UCHAR *PUCHAR;
|
||||||
|
[string] typedef CHAR *PSTR;
|
||||||
|
[string] typedef const CHAR *PCSTR;
|
||||||
|
|
||||||
|
/* Boolean type */
|
||||||
|
typedef int BOOL;
|
||||||
|
|
||||||
|
/* Status code/result types */
|
||||||
|
typedef UINT32 SCODE;
|
||||||
|
typedef SCODE HRESULT;
|
||||||
|
|
||||||
|
/* GUID typedefs */
|
||||||
|
typedef struct tagGUID {
|
||||||
|
UINT32 Data1;
|
||||||
|
UINT16 Data2;
|
||||||
|
UINT16 Data3;
|
||||||
|
BYTE Data4[8];
|
||||||
|
} GUID;
|
||||||
|
typedef GUID IID;
|
||||||
|
typedef GUID CLSID;
|
||||||
|
|
||||||
|
/* The reference types are defined specially so we can use C++ references where necessary */
|
||||||
|
cpp_quote("#if !defined(__cplusplus) || defined(CINTERFACE)")
|
||||||
|
typedef const GUID *REFGUID;
|
||||||
|
typedef const IID *REFIID;
|
||||||
|
typedef const CLSID *REFCLSID;
|
||||||
|
cpp_quote("#endif")
|
||||||
|
}
|
||||||
|
|
||||||
|
cpp_quote("#if defined(__cplusplus) && !defined(CINTERFACE)")
|
||||||
|
cpp_quote("typedef const GUID& REFGUID;")
|
||||||
|
cpp_quote("typedef const IID& REFIID;")
|
||||||
|
cpp_quote("typedef const CLSID& REFCLSID;")
|
||||||
|
cpp_quote("#endif")
|
||||||
|
|
58
idl/comrogue/objectbase.idl
Normal file
58
idl/comrogue/objectbase.idl
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
/*
|
||||||
|
* This file is part of the COMROGUE Operating System for Raspberry Pi
|
||||||
|
*
|
||||||
|
* Copyright (c) 2013, Eric J. Bowersox / Erbosoft Enterprises
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This program is free for commercial and non-commercial use as long as the following conditions are
|
||||||
|
* adhered to.
|
||||||
|
*
|
||||||
|
* Copyright in this file remains Eric J. Bowersox and/or Erbosoft, and as such any copyright notices
|
||||||
|
* in the code are not to be removed.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification, are permitted
|
||||||
|
* provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* * Redistributions of source code must retain the above copyright notice, this list of conditions and
|
||||||
|
* the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
|
||||||
|
* the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
|
||||||
|
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||||
|
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||||
|
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* "Raspberry Pi" is a trademark of the Raspberry Pi Foundation.
|
||||||
|
*/
|
||||||
|
import "comrogue/object_types.idl";
|
||||||
|
|
||||||
|
/*--------------------
|
||||||
|
* IUnknown interface
|
||||||
|
*--------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
[object, uuid(00000000-0000-0000-C000-000000000046), pointer_default(unique)]
|
||||||
|
interface IUnknown
|
||||||
|
{
|
||||||
|
[unique] typedef IUnknown *PUNKNOWN;
|
||||||
|
HRESULT QueryInterface([in] REFIID riid, [out, iid_is(riid)] PPVOID ppvObject);
|
||||||
|
UINT32 AddRef();
|
||||||
|
UINT32 Release();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*----------------------------
|
||||||
|
* IServiceProvider interface
|
||||||
|
*----------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
[object, uuid(6d5140c1-7436-11ce-8034-00aa006009fa), pointer_default(unique)]
|
||||||
|
interface IServiceProvider : IUnknown
|
||||||
|
{
|
||||||
|
[unique] typedef IServiceProvider *PSERVICEPROVIDER;
|
||||||
|
HRESULT QueryService([in] REFGUID guidService, [in] REFIID riid, [out, iid_is(riid)] PPVOID ppvObject);
|
||||||
|
}
|
58
include/comrogue/compiler_macros.h
Normal file
58
include/comrogue/compiler_macros.h
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
/*
|
||||||
|
* This file is part of the COMROGUE Operating System for Raspberry Pi
|
||||||
|
*
|
||||||
|
* Copyright (c) 2013, Eric J. Bowersox / Erbosoft Enterprises
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This program is free for commercial and non-commercial use as long as the following conditions are
|
||||||
|
* adhered to.
|
||||||
|
*
|
||||||
|
* Copyright in this file remains Eric J. Bowersox and/or Erbosoft, and as such any copyright notices
|
||||||
|
* in the code are not to be removed.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification, are permitted
|
||||||
|
* provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* * Redistributions of source code must retain the above copyright notice, this list of conditions and
|
||||||
|
* the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
|
||||||
|
* the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
|
||||||
|
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||||
|
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||||
|
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* "Raspberry Pi" is a trademark of the Raspberry Pi Foundation.
|
||||||
|
*/
|
||||||
|
#ifndef __COMPILER_MACROS_H_INCLUDED
|
||||||
|
#define __COMPILER_MACROS_H_INCLUDED
|
||||||
|
|
||||||
|
#ifndef __ASM__
|
||||||
|
|
||||||
|
/*--------------------------------------------------------------------------
|
||||||
|
* Compiler macros for differentiationg between C++ and C compilation, etc.
|
||||||
|
*--------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
|
||||||
|
#define EXTERN_C extern "C"
|
||||||
|
#define CDECL_BEGIN extern "C" {
|
||||||
|
#define CDECL_END }
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#define EXTERN_C
|
||||||
|
#define CDECL_BEGIN
|
||||||
|
#define CDECL_END
|
||||||
|
|
||||||
|
#endif /* __cplusplus */
|
||||||
|
|
||||||
|
#endif /* __ASM__ */
|
||||||
|
|
||||||
|
#endif /* __COMPILER_MACROS_H_INCLUDED */
|
141
include/comrogue/internals/16550.h
Normal file
141
include/comrogue/internals/16550.h
Normal file
|
@ -0,0 +1,141 @@
|
||||||
|
/*
|
||||||
|
* This file is part of the COMROGUE Operating System for Raspberry Pi
|
||||||
|
*
|
||||||
|
* Copyright (c) 2013, Eric J. Bowersox / Erbosoft Enterprises
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This program is free for commercial and non-commercial use as long as the following conditions are
|
||||||
|
* adhered to.
|
||||||
|
*
|
||||||
|
* Copyright in this file remains Eric J. Bowersox and/or Erbosoft, and as such any copyright notices
|
||||||
|
* in the code are not to be removed.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification, are permitted
|
||||||
|
* provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* * Redistributions of source code must retain the above copyright notice, this list of conditions and
|
||||||
|
* the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
|
||||||
|
* the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
|
||||||
|
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||||
|
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||||
|
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* "Raspberry Pi" is a trademark of the Raspberry Pi Foundation.
|
||||||
|
*/
|
||||||
|
#ifndef __X__16550_H_INCLUDED
|
||||||
|
#define __X__16550_H_INCLUDED
|
||||||
|
|
||||||
|
#ifdef __COMROGUE_INTERNALS__
|
||||||
|
|
||||||
|
/*------------------------------------------------------------------------------------------------------------
|
||||||
|
* Standard bits used in the registers of a 16550 UART. Note that not all of these bits are supported by the
|
||||||
|
* BCM2835 mini-UART; they are included here for completeness.
|
||||||
|
*------------------------------------------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Interrupt Enable Register (read/write) */
|
||||||
|
#define U16550_IER_RXREADY 0x01 /* Receive Ready interrupt */
|
||||||
|
#define U16550_IER_TXEMPTY 0x02 /* Transmit Empty interrupt */
|
||||||
|
#define U16550_IER_ERRBRK 0x04 /* Error/Break iterrupt */
|
||||||
|
#define U16550_IER_SINPUT 0x08 /* Status change interrupt */
|
||||||
|
|
||||||
|
/* Interrupt Identification Register (read-only) */
|
||||||
|
#define U16550_IIR_NOPENDING 0x01 /* Set if no interrupt is pending */
|
||||||
|
#define U16550_IIR_ID_MASK 0x0E /* Pending interrupt mask */
|
||||||
|
#define U16550_IIR_ID_ERRBRK 0x06 /* Error/Break interrupt */
|
||||||
|
#define U16550_IIR_ID_RXREADY 0x04 /* Receive Ready interrupt */
|
||||||
|
#define U16550_IIR_ID_RXTIMEOUT 0x0C /* Receive Timeout interrupt */
|
||||||
|
#define U16550_IIR_ID_TXEMPTY 0x02 /* Transmit Empty interrupt */
|
||||||
|
#define U16550_IIR_ID_SINPUT 0x00 /* Status change interrupt */
|
||||||
|
#define U16550_IIR_RXFIFO 0x40 /* Receive FIFO enabled */
|
||||||
|
#define U16550_IIR_TXFIFO 0x80 /* Transmit FIFO enabled */
|
||||||
|
|
||||||
|
/* FIFO Control Register (write-only) */
|
||||||
|
#define U16550_FCR_ENABLE 0x01 /* Enable FIFOs */
|
||||||
|
#define U16550_FCR_RXCLEAR 0x02 /* Clear receive FIFO */
|
||||||
|
#define U16550_FCR_TXCLEAR 0x04 /* Clear transmit FIFO */
|
||||||
|
#define U16550_FCR_MODE 0x08 /* FIFO mode select */
|
||||||
|
#define U16550_FCR_LEVEL_MASK 0xC0 /* FIFO level mask */
|
||||||
|
#define U16550_FCR_LEVEL_1 0x00 /* FIFO level: 1 character */
|
||||||
|
#define U16550_FCR_LEVEL_4 0x40 /* FIFO level: 4 characters */
|
||||||
|
#define U16550_FCR_LEVEL_8 0x80 /* FIFO level: 8 characters */
|
||||||
|
#define U16550_FCR_LEVEL_14 0xC0 /* FIFO level: 14 characters */
|
||||||
|
|
||||||
|
/* Line Control Register (read/write) */
|
||||||
|
#define U16550_LCR_LENGTH_MASK 0x03 /* Data length control mask */
|
||||||
|
#define U16550_LCR_LENGTH_5 0x00 /* Data length: 5 bits */
|
||||||
|
#define U16550_LCR_LENGTH_6 0x01 /* Data length: 6 bits */
|
||||||
|
#define U16550_LCR_LENGTH_7 0x02 /* Data length: 7 bits */
|
||||||
|
#define U16550_LCR_LENGTH_8 0x03 /* Data length: 8 bits */
|
||||||
|
#define U16550_LCR_STOP 0x04 /* Set = 2 stop bits, Clear = 1 stop bit */
|
||||||
|
#define U16550_LCR_PARITY_MASK 0x38 /* Parity control mask */
|
||||||
|
#define U16550_LCR_PARITY_NONE 0x00 /* Parity: NONE */
|
||||||
|
#define U16550_LCR_PARITY_ODD 0x08 /* Parity: ODD */
|
||||||
|
#define U16550_LCR_PARITY_EVEN 0x18 /* Parity: EVEN */
|
||||||
|
#define U16550_LCR_PARITY_MARK 0x28 /* Parity: MARK */
|
||||||
|
#define U16550_LCR_PARITY_SPACE 0x38 /* Parity: SPACE */
|
||||||
|
#define U16550_LCR_BREAK 0x40 /* Send BREAK when set */
|
||||||
|
#define U16550_LCR_DLAB 0x80 /* Divisor Latch Access Bit */
|
||||||
|
|
||||||
|
/* Modem Control Register (read/write) */
|
||||||
|
#define U16550_MCR_DTR 0x01 /* Set Data Terminal Ready */
|
||||||
|
#define U16550_MCR_RTS 0x02 /* Set Request To Send */
|
||||||
|
#define U16550_MCR_OP1 0x04 /* Set General-Purpose Output 1 */
|
||||||
|
#define U16550_MCR_OP2 0x08 /* Set General-Purpose Output 2 */
|
||||||
|
#define U16550_MCR_LOOPBACK 0x10 /* Loopback test mode */
|
||||||
|
|
||||||
|
/* Line Status Register (read-only) */
|
||||||
|
#define U16550_LSR_RXDATA 0x01 /* Received data ready */
|
||||||
|
#define U16550_LSR_OVERRUNERR 0x02 /* Receiver overrun error */
|
||||||
|
#define U16550_LSR_PARITYERR 0x04 /* Parity error */
|
||||||
|
#define U16550_LSR_FRAMEERR 0x08 /* Framing error */
|
||||||
|
#define U16550_LSR_BREAK 0x10 /* BREAK detected */
|
||||||
|
#define U16550_LSR_TXBUFEMPTY 0x20 /* Transmitter buffer empty */
|
||||||
|
#define U16550_LSR_TXEMPTY 0x40 /* Transmitter empty */
|
||||||
|
|
||||||
|
/* Modem Status Register (read-only) */
|
||||||
|
#define U16550_MSR_DELTA_CTS 0x01 /* change in Clear To Send line */
|
||||||
|
#define U16550_MSR_DELTA_DSR 0x02 /* change in Data Set Ready line */
|
||||||
|
#define U16550_MSR_DELTA_RI 0x04 /* change in Ring Indicator line */
|
||||||
|
#define U16550_MSR_DELTA_CD 0x08 /* change in Carrier Detect line */
|
||||||
|
#define U16550_MSR_CTS 0x10 /* Clear To Send */
|
||||||
|
#define U16550_MSR_DSR 0x20 /* Data Set Ready */
|
||||||
|
#define U16550_MSR_RI 0x40 /* Ring Indicator */
|
||||||
|
#define U16550_MSR_CD 0x80 /* Carrier Detect */
|
||||||
|
|
||||||
|
/* BCM2835-specific: Auxiliary control register (read/write) */
|
||||||
|
#define AUXMU_CNTL_RXENABLE 0x00000001 /* Receiver enable */
|
||||||
|
#define AUXMU_CNTL_TXENABLE 0x00000002 /* Transmitter enable */
|
||||||
|
#define AUXMU_CNTL_RXAUTOFLOW 0x00000004 /* Reciever auto-flow-control enabled */
|
||||||
|
#define AUXMU_CNTL_TXAUTOFLOW 0x00000008 /* Transmitter auto-flow-control enabled */
|
||||||
|
#define AUXMU_CNTL_RXAUTO_MASK 0x00000030 /* Receiver auto-flow-control level */
|
||||||
|
#define AUXMU_CNTL_RXAUTO_3 0x00000000 /* Receiver auto-flow-control: 3 spaces remaining */
|
||||||
|
#define AUXMU_CNTL_RXAUTO_2 0x00000010 /* Receiver auto-flow-control: 2 spaces remaining */
|
||||||
|
#define AUXMU_CNTL_RXAUTO_1 0x00000020 /* Receiver auto-flow-control: 1 space remaining */
|
||||||
|
#define AUXMU_CNTL_RXAUTO_4 0x00000030 /* Receiver auto-flow-control: 4 spaces remaining */
|
||||||
|
#define AUXMU_CNTL_RTSASSERT 0x00000040 /* RTS assert level invert */
|
||||||
|
#define AUXMU_CNTL_CTSASSERT 0x00000080 /* CTS assert level invert */
|
||||||
|
|
||||||
|
/* BCM2835-specific: Auxiliary status register (read-only) */
|
||||||
|
#define AUXMU_STAT_RXREADY 0x00000001 /* Receive ready */
|
||||||
|
#define AUXMU_STAT_TXREADY 0x00000002 /* Transmit ready */
|
||||||
|
#define AUXMU_STAT_RXIDLE 0x00000004 /* Receiver idle */
|
||||||
|
#define AUXMU_STAT_TXIDLE 0x00000008 /* Transmitter idle */
|
||||||
|
#define AUXMU_STAT_RXOVERRUN 0x00000010 /* Receiver overrun */
|
||||||
|
#define AUXMU_STAT_TXFULL 0x00000020 /* Transmit FIFO is full */
|
||||||
|
#define AUXMU_STAT_RTS 0x00000040 /* Request To Send line */
|
||||||
|
#define AUXMU_STAT_CTS 0x00000080 /* Clear To Send line */
|
||||||
|
#define AUXMU_STAT_TXDONE 0x00000100 /* Transmitter done (Tx idle, FIFO empty) */
|
||||||
|
#define AUXMU_STAT_RXLEVEL_MASK 0x000F0000 /* Receive FIFO fill level mask */
|
||||||
|
#define AUXMU_STAT_TXLEVEL_MASK 0x0F000000 /* Transmit FIFO fill level mask */
|
||||||
|
|
||||||
|
#endif /* __COMROGUE_INTERNALS__ */
|
||||||
|
|
||||||
|
#endif /* __X__16550_H_INCLUDED */
|
58
include/comrogue/internals/asm-macros.h
Normal file
58
include/comrogue/internals/asm-macros.h
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
/*
|
||||||
|
* This file is part of the COMROGUE Operating System for Raspberry Pi
|
||||||
|
*
|
||||||
|
* Copyright (c) 2013, Eric J. Bowersox / Erbosoft Enterprises
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This program is free for commercial and non-commercial use as long as the following conditions are
|
||||||
|
* adhered to.
|
||||||
|
*
|
||||||
|
* Copyright in this file remains Eric J. Bowersox and/or Erbosoft, and as such any copyright notices
|
||||||
|
* in the code are not to be removed.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification, are permitted
|
||||||
|
* provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* * Redistributions of source code must retain the above copyright notice, this list of conditions and
|
||||||
|
* the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
|
||||||
|
* the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
|
||||||
|
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||||
|
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||||
|
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* "Raspberry Pi" is a trademark of the Raspberry Pi Foundation.
|
||||||
|
*/
|
||||||
|
#ifndef __ASM_MACROS_H_INCLUDED
|
||||||
|
#define __ASM_MACROS_H_INCLUDED
|
||||||
|
|
||||||
|
#ifdef __COMROGUE_INTERNALS__
|
||||||
|
|
||||||
|
#ifndef __ASM__
|
||||||
|
#error "This file should be included in assembly language code only"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Instruction barrier macro */
|
||||||
|
.macro instr_barrier
|
||||||
|
mcr p15, 0, r0, c7, c5, 4
|
||||||
|
.endm
|
||||||
|
|
||||||
|
/* Data synchronization barrier macro */
|
||||||
|
.macro data_sync_barrier
|
||||||
|
mcr p15, 0, r0, c7, c10, 4
|
||||||
|
.endm
|
||||||
|
|
||||||
|
/* Data memory barrier macro */
|
||||||
|
.macro data_memory_barrier
|
||||||
|
mcr p15, 0, r0, c7, c10, 5
|
||||||
|
.endm
|
||||||
|
|
||||||
|
#endif /* __COMROGUE_INTERNALS__ */
|
||||||
|
|
||||||
|
#endif /* __ASM_MACROS_H_INCLUDED */
|
81
include/comrogue/internals/auxdev.h
Normal file
81
include/comrogue/internals/auxdev.h
Normal file
|
@ -0,0 +1,81 @@
|
||||||
|
/*
|
||||||
|
* This file is part of the COMROGUE Operating System for Raspberry Pi
|
||||||
|
*
|
||||||
|
* Copyright (c) 2013, Eric J. Bowersox / Erbosoft Enterprises
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This program is free for commercial and non-commercial use as long as the following conditions are
|
||||||
|
* adhered to.
|
||||||
|
*
|
||||||
|
* Copyright in this file remains Eric J. Bowersox and/or Erbosoft, and as such any copyright notices
|
||||||
|
* in the code are not to be removed.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification, are permitted
|
||||||
|
* provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* * Redistributions of source code must retain the above copyright notice, this list of conditions and
|
||||||
|
* the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
|
||||||
|
* the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
|
||||||
|
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||||
|
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||||
|
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* "Raspberry Pi" is a trademark of the Raspberry Pi Foundation.
|
||||||
|
*/
|
||||||
|
#ifndef __AUXDEV_H_INCLUDED
|
||||||
|
#define __AUXDEV_H_INCLUDED
|
||||||
|
|
||||||
|
#ifdef __COMROGUE_INTERNALS__
|
||||||
|
|
||||||
|
/*-------------------------------
|
||||||
|
* BCM2835 auxiliary peripherals
|
||||||
|
*-------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Register physical addresses */
|
||||||
|
#define AUX_REG_IRQ 0x20215000 /* AUX interrupt status */
|
||||||
|
#define AUX_REG_ENABLE 0x20215004 /* AUX enable */
|
||||||
|
#define AUX_MU_REG_THR 0x20215040 /* Mini-UART Transmitter Holding Register */
|
||||||
|
#define AUX_MU_REG_RHR 0x20215040 /* Mini-UART Receiver Holding Register */
|
||||||
|
#define AUX_MU_REG_IER 0x20215044 /* Mini-UART Interrupt Enable Register */
|
||||||
|
#define AUX_MU_REG_IIR 0x20215048 /* Mini-UART Interrupt Identification Register */
|
||||||
|
#define AUX_MU_REG_FCR 0x20215048 /* Mini-UART FIFO Control Register */
|
||||||
|
#define AUX_MU_REG_LCR 0x2021504C /* Mini-UART Line Control Register */
|
||||||
|
#define AUX_MU_REG_MCR 0x20215050 /* Mini-UART Modem Control Register */
|
||||||
|
#define AUX_MU_REG_LSR 0x20215054 /* Mini-UART Line Status Register */
|
||||||
|
#define AUX_MU_REG_MSR 0x20215058 /* Mini-UART Modem Status Register */
|
||||||
|
#define AUX_MU_REG_SCR 0x2021505C /* Mini-UART Scratch Register */
|
||||||
|
#define AUX_MU_REG_CNTL 0x20215060 /* Mini-UART Auxiliary Control Register */
|
||||||
|
#define AUX_MU_REG_STAT 0x20215064 /* Mini-UART Auxiliary Status Register */
|
||||||
|
#define AUX_MU_REG_BAUD 0x20215068 /* Mini-UART Baud Rate Register */
|
||||||
|
#define AUX_SPI0_REG_CTL0 0x20215080 /* SPI 0 Control Register 0 */
|
||||||
|
#define AUX_SPI0_REG_CTL1 0x20215084 /* SPI 0 Control Register 1 */
|
||||||
|
#define AUX_SPI0_REG_STAT 0x20215088 /* SPI 0 Status Register */
|
||||||
|
#define AUX_SPI0_REG_IO 0x20215090 /* SPI 0 Data Register */
|
||||||
|
#define AUX_SPI0_REG_PEEK 0x20215094 /* SPI 0 Peek Register */
|
||||||
|
#define AUX_SPI1_REG_CTL0 0x202150C0 /* SPI 1 Control Register 0 */
|
||||||
|
#define AUX_SPI1_REG_CTL1 0x202150C4 /* SPI 1 Control Register 1 */
|
||||||
|
#define AUX_SPI1_REG_STAT 0x202150C8 /* SPI 1 Status Register */
|
||||||
|
#define AUX_SPI1_REG_IO 0x202150D0 /* SPI 1 Data Register */
|
||||||
|
#define AUX_SPI1_REG_PEEK 0x202150D4 /* SPI 1 Peek Register */
|
||||||
|
|
||||||
|
/* AUX IRQ register bits */
|
||||||
|
#define AUX_IRQ_MU 0x00000001 /* Mini-UART has interrupt pending */
|
||||||
|
#define AUX_IRQ_SPI0 0x00000002 /* SPI 0 has interrupt pending */
|
||||||
|
#define AUX_IRQ_SPI1 0x00000004 /* SPI 1 has interrupt pending */
|
||||||
|
|
||||||
|
/* AUX Enable register bits */
|
||||||
|
#define AUX_ENABLE_MU 0x00000001 /* Mini-UART enable */
|
||||||
|
#define AUX_ENABLE_SPI0 0x00000002 /* SPI 0 enable */
|
||||||
|
#define AUX_ENABLE_SPI1 0x00000004 /* SPI 1 enable */
|
||||||
|
|
||||||
|
#endif /* __COMROGUE_INTERNALS__ */
|
||||||
|
|
||||||
|
#endif /* __AUXDEV_H_INCLUDED__ */
|
93
include/comrogue/internals/gpio.h
Normal file
93
include/comrogue/internals/gpio.h
Normal file
|
@ -0,0 +1,93 @@
|
||||||
|
/*
|
||||||
|
* This file is part of the COMROGUE Operating System for Raspberry Pi
|
||||||
|
*
|
||||||
|
* Copyright (c) 2013, Eric J. Bowersox / Erbosoft Enterprises
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This program is free for commercial and non-commercial use as long as the following conditions are
|
||||||
|
* adhered to.
|
||||||
|
*
|
||||||
|
* Copyright in this file remains Eric J. Bowersox and/or Erbosoft, and as such any copyright notices
|
||||||
|
* in the code are not to be removed.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification, are permitted
|
||||||
|
* provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* * Redistributions of source code must retain the above copyright notice, this list of conditions and
|
||||||
|
* the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
|
||||||
|
* the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
|
||||||
|
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||||
|
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||||
|
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* "Raspberry Pi" is a trademark of the Raspberry Pi Foundation.
|
||||||
|
*/
|
||||||
|
#ifndef __GPIO_H_INCLUDED
|
||||||
|
#define __GPIO_H_INCLUDED
|
||||||
|
|
||||||
|
#ifdef __COMROGUE_INTERNALS__
|
||||||
|
|
||||||
|
/*--------------------
|
||||||
|
* BCM2835 GPIO lines
|
||||||
|
*--------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* GPIO register physical addresses */
|
||||||
|
#define GPFSEL0_REG 0x20200000 /* GPIO Function Select 0 (lines 0-9) */
|
||||||
|
#define GPFSEL1_REG 0x20200004 /* GPIO Function Select 1 (lines 10-19) */
|
||||||
|
#define GPFSEL2_REG 0x20200008 /* GPIO Function Select 2 (lines 20-29) */
|
||||||
|
#define GPFSEL3_REG 0x2020000C /* GPIO Function Select 3 (lines 30-39) */
|
||||||
|
#define GPFSEL4_REG 0x20200010 /* GPIO Function Select 4 (lines 40-49) */
|
||||||
|
#define GPFSEL5_REG 0x20200014 /* GPIO Function Select 5 (lines 50-53) */
|
||||||
|
#define GPSET0_REG 0x2020001C /* GPIO Output Set 0 (lines 0-31) */
|
||||||
|
#define GPSET1_REG 0x20200020 /* GPIO Output Set 1 (lines 32-53) */
|
||||||
|
#define GPCLR0_REG 0x20200028 /* GPIO Output Clear 0 (lines 0-31) */
|
||||||
|
#define GPCLR1_REG 0x2020002C /* GPIO Output Clear 1 (lines 32-53) */
|
||||||
|
#define GPLEV0_REG 0x20200034 /* GPIO Pin Level Detect 0 (lines 0-31) */
|
||||||
|
#define GPLEV1_REG 0x20200038 /* GPIO Pin Level Detect 1 (lines 32-53) */
|
||||||
|
#define GPEDS0_REG 0x20200040 /* GPIO Pin Event Detect Status 0 (lines 0-31) */
|
||||||
|
#define GPEDS1_REG 0x20200044 /* GPIO Pin Event Detect Status 1 (lines 32-53) */
|
||||||
|
#define GPREN0_REG 0x2020004C /* GPIO Pin Rising Edge Detect Enable 0 (lines 0-31) */
|
||||||
|
#define GPREN1_REG 0x20200050 /* GPIO Pin Rising Edge Detect Enable 1 (lines 32-53) */
|
||||||
|
#define GPFEN0_REG 0x20200085 /* GPIO Pin Falling Edge Detect Enable 0 (lines 0-31) */
|
||||||
|
#define GPFEN1_REG 0x2020005C /* GPIO Pin Falling Edge Detect Enable 1 (lines 32-53) */
|
||||||
|
#define GPHEN0_REG 0x20200064 /* GPIO Pin High Level Detect Enable 0 (lines 0-31) */
|
||||||
|
#define GPHEN1_REG 0x20200068 /* GPIO Pin High Level Detect Enable 1 (lines 32-53) */
|
||||||
|
#define GPLEN0_REG 0x20200070 /* GPIO Pin Low Level Detect Enable 0 (lines 0-31) */
|
||||||
|
#define GPLEN1_REG 0x20200074 /* GPIO Pin Low Level Detect Enable 1 (lines 32-53) */
|
||||||
|
#define GPAREN0_REG 0x2020007C /* GPIO Pin Async Rising Edge Detect Enable 0 (lines 0-31) */
|
||||||
|
#define GPAREN1_REG 0x20200080 /* GPIO Pin Async Rising Edge Detect Enable 1 (lines 32-53) */
|
||||||
|
#define GPAFEN0_REG 0x20200088 /* GPIO Pin Async Falling Edge Detect Enable 0 (lines 0-31) */
|
||||||
|
#define GPAFEN1_REG 0x2020008C /* GPIO Pin Async Falling Edge Detect Enable 1 (lines 32-53) */
|
||||||
|
#define GPPUD_REG 0x20200094 /* GPIO Pin Pull-up/down Enable */
|
||||||
|
#define GPPUDCLK0_REG 0x20200098 /* GPIO Pin Pull-up/down Enable Clock 0 (lines 0-31) */
|
||||||
|
#define GPPUDCLK1_REG 0x2020009C /* GPIO Pin Pull-up/down Enable Clock 1 (lines 32-53) */
|
||||||
|
|
||||||
|
#define GP_PIN_MASK 0x0007 /* GPIO pin function select mask */
|
||||||
|
#define GP_PIN_INPUT 0x0000 /* GPIO pin function is input */
|
||||||
|
#define GP_PIN_OUTPUT 0x0001 /* GPIO pin function is output */
|
||||||
|
#define GP_PIN_ALT0 0x0004 /* GPIO pin alternate function 0 */
|
||||||
|
#define GP_PIN_ALT1 0x0005 /* GPIO pin alternate function 1 */
|
||||||
|
#define GP_PIN_ALT2 0x0006 /* GPIO pin alternate function 2 */
|
||||||
|
#define GP_PIN_ALT3 0x0007 /* GPIO pin alternate function 3 */
|
||||||
|
#define GP_PIN_ALT4 0x0003 /* GPIO pin alternate function 4 */
|
||||||
|
#define GP_PIN_ALT5 0x0002 /* GPIO pin alternate function 5 */
|
||||||
|
|
||||||
|
#define GP_FUNC_MASK(n) (GP_PIN_MASK << ((n) * 3))
|
||||||
|
#define GP_FUNC_BITS(n, bits) (((bits) & GP_PIN_MASK) << ((n) * 3))
|
||||||
|
#define GP_BIT(n) (1 << (n))
|
||||||
|
|
||||||
|
#define GPPUD_DISABLE 0x0000 /* Disable pull-up/pull-down */
|
||||||
|
#define GPPUD_PULLDOWN 0x0001 /* Enable pull-down */
|
||||||
|
#define GPPUD_PULLUP 0x0002 /* Enable pull-up */
|
||||||
|
|
||||||
|
#endif /* __COMROGUE_INTERNALS__ */
|
||||||
|
|
||||||
|
#endif /* __GPIO_H_INCLUDED */
|
52
include/comrogue/internals/layout.h
Normal file
52
include/comrogue/internals/layout.h
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
/*
|
||||||
|
* This file is part of the COMROGUE Operating System for Raspberry Pi
|
||||||
|
*
|
||||||
|
* Copyright (c) 2013, Eric J. Bowersox / Erbosoft Enterprises
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This program is free for commercial and non-commercial use as long as the following conditions are
|
||||||
|
* adhered to.
|
||||||
|
*
|
||||||
|
* Copyright in this file remains Eric J. Bowersox and/or Erbosoft, and as such any copyright notices
|
||||||
|
* in the code are not to be removed.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification, are permitted
|
||||||
|
* provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* * Redistributions of source code must retain the above copyright notice, this list of conditions and
|
||||||
|
* the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
|
||||||
|
* the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
|
||||||
|
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||||
|
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||||
|
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* "Raspberry Pi" is a trademark of the Raspberry Pi Foundation.
|
||||||
|
*/
|
||||||
|
#ifndef __LAYOUT_H_INCLUDED
|
||||||
|
#define __LAYOUT_H_INCLUDED
|
||||||
|
|
||||||
|
#ifdef __COMROGUE_INTERNALS__
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------
|
||||||
|
* Constants defining the layout of the COMROGUE memory map.
|
||||||
|
*-----------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define PHYSADDR_LOAD 0x8000 /* physical address at which the loader loads the kernel */
|
||||||
|
#define PHYSADDR_IO_BASE 0x20000000 /* physical address that's the base for memory-mapped IO */
|
||||||
|
#define VMADDR_TTB_FENCE 0x80000000 /* address that's the dividing point between TTBs */
|
||||||
|
#define VMADDR_LIBRARY_FENCE 0xB0000000 /* base address for kernel "shared library" code */
|
||||||
|
#define VMADDR_KERNEL_FENCE 0xC0000000 /* base address for the internal kernel code */
|
||||||
|
#define VMADDR_IO_BASE 0xE0000000 /* base address for memory-mapped IO */
|
||||||
|
#define PAGE_COUNT_IO 1024 /* 4 megabytes mapped for IO */
|
||||||
|
|
||||||
|
#endif /* __COMROGUE_INTERNALS__ */
|
||||||
|
|
||||||
|
#endif /* __LAYOUT_H_INCLUDED */
|
51
include/comrogue/internals/llio.h
Normal file
51
include/comrogue/internals/llio.h
Normal file
|
@ -0,0 +1,51 @@
|
||||||
|
#ifndef __LLIO_H_INCLUDED
|
||||||
|
#define __LLIO_H_INCLUDED
|
||||||
|
|
||||||
|
#ifdef __COMROGUE_INTERNALS__
|
||||||
|
|
||||||
|
#ifndef __ASM__
|
||||||
|
|
||||||
|
#include <comrogue/types.h>
|
||||||
|
#include <comrogue/compiler_macros.h>
|
||||||
|
|
||||||
|
/*--------------------------------------------------------------------------------------
|
||||||
|
* Functions for performing low-level IO (direct read and write of memory-mapped ports)
|
||||||
|
*--------------------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef __COMROGUE_PRESTART__
|
||||||
|
|
||||||
|
CDECL_BEGIN
|
||||||
|
|
||||||
|
extern void llIOWritePA(PHYSADDR paPort, UINT32 uiData);
|
||||||
|
extern UINT32 llIOReadPA(PHYSADDR paPort);
|
||||||
|
extern void llIODelayPA(UINT32 uiTicks);
|
||||||
|
|
||||||
|
#define llIOWrite(addr, data) llIOWritePA(addr, data)
|
||||||
|
#define llIORead(addr) llIOReadPA(addr)
|
||||||
|
#define llIODelay(ticks) llIODelayPA(ticks)
|
||||||
|
|
||||||
|
CDECL_END
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
CDECL_BEGIN
|
||||||
|
|
||||||
|
extern void llIOWriteK(KERNADDR kaPort, UINT32 uiData);
|
||||||
|
extern UINT32 llIOReadK(KERNADDR kaPort);
|
||||||
|
extern void llIODelay(UINT32 uiTicks);
|
||||||
|
|
||||||
|
CDECL_END
|
||||||
|
|
||||||
|
#define _LLIOMAP(addr) ((addr) + 0xC0000000)
|
||||||
|
|
||||||
|
#define llIOWrite(addr, data) llIOWriteK(_LLIOMAP(addr), data)
|
||||||
|
#define llIORead(addr) llIOReadK(_LLIOMAP(addr))
|
||||||
|
|
||||||
|
#endif /* __COMROGUE_PRESTART__ */
|
||||||
|
|
||||||
|
#endif /* __ASM__ */
|
||||||
|
|
||||||
|
#endif /* __COMROGUE_INTERNALS__ */
|
||||||
|
|
||||||
|
#endif /* __LLIO_H_INCLUDED */
|
241
include/comrogue/internals/mmu.h
Normal file
241
include/comrogue/internals/mmu.h
Normal file
|
@ -0,0 +1,241 @@
|
||||||
|
/*
|
||||||
|
* This file is part of the COMROGUE Operating System for Raspberry Pi
|
||||||
|
*
|
||||||
|
* Copyright (c) 2013, Eric J. Bowersox / Erbosoft Enterprises
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This program is free for commercial and non-commercial use as long as the following conditions are
|
||||||
|
* adhered to.
|
||||||
|
*
|
||||||
|
* Copyright in this file remains Eric J. Bowersox and/or Erbosoft, and as such any copyright notices
|
||||||
|
* in the code are not to be removed.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification, are permitted
|
||||||
|
* provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* * Redistributions of source code must retain the above copyright notice, this list of conditions and
|
||||||
|
* the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
|
||||||
|
* the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
|
||||||
|
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||||
|
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||||
|
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* "Raspberry Pi" is a trademark of the Raspberry Pi Foundation.
|
||||||
|
*/
|
||||||
|
#ifndef __MMU_H_INCLUDED
|
||||||
|
#define __MMU_H_INCLUDED
|
||||||
|
|
||||||
|
#ifdef __COMROGUE_INTERNALS__
|
||||||
|
|
||||||
|
/*----------------------------------------------
|
||||||
|
* BCM2835 ARM Memory Management Unit constants
|
||||||
|
*----------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Memory system constants */
|
||||||
|
#define SYS_PAGE_SIZE 4096 /* standard page size for normal page */
|
||||||
|
#define SYS_PAGE_BITS 12 /* log2(SYS_PAGE_SIZE), number of bits in a page address */
|
||||||
|
#define SYS_TTB0_SIZE 8192 /* TTB0 must be located on this boundary and is this size */
|
||||||
|
#define SYS_TTB1_SIZE 16384 /* TTB1 must be located on this boundary and is this size */
|
||||||
|
#define SYS_TTB1_ENTRIES 4096 /* SYS_TTB1_SIZE/4, number of entries in TTB1 */
|
||||||
|
#define SYS_TTB_BITS 12 /* log2(SYS_TTB1_SIZE/4), number of bits in a TTB address */
|
||||||
|
#define SYS_SEC_SIZE 1048576 /* standard section size */
|
||||||
|
#define SYS_SEC_PAGES 256 /* SYS_SEC_SIZE/SYS_PAGE_SIZE, number of pages equivalent to a section */
|
||||||
|
#define SYS_PGTBL_SIZE 1024 /* page tables must be located on this boundary and are this size */
|
||||||
|
#define SYS_PGTBL_BITS 8 /* log2(SYS_PGTBL_SIZE/4), number of bits in a page table address */
|
||||||
|
#define SYS_PGTBL_ENTRIES 256 /* SYS_PGTBL_SIZE/4, number of entries in a page table */
|
||||||
|
|
||||||
|
/* Section descriptor bits */
|
||||||
|
#define TTBSEC_PXN 0x00000001 /* Privileged Execute-Never */
|
||||||
|
#define TTBSEC_ALWAYS 0x00000002 /* this bit must always be set for a section */
|
||||||
|
#define TTBSEC_B 0x00000004 /* memory region attribute bit */
|
||||||
|
#define TTBSEC_C 0x00000008 /* memory region attribute bit */
|
||||||
|
#define TTBSEC_XN 0x00000010 /* Execute-Never */
|
||||||
|
#define TTBSEC_DOM_MASK 0x000001E0 /* domain indicator */
|
||||||
|
#define TTBSEC_P 0x00000200 /* ECC enabled (not supported) */
|
||||||
|
#define TTBSEC_AP 0x00000C00 /* access permission bits */
|
||||||
|
#define TTBSEC_TEX 0x00007000 /* memory type flags */
|
||||||
|
#define TTBSEC_APX 0x00008000 /* access permission extended */
|
||||||
|
#define TTBSEC_S 0x00010000 /* Shared */
|
||||||
|
#define TTBSEC_NG 0x00020000 /* Not Global */
|
||||||
|
#define TTBSEC_SUPER 0x00040000 /* Set for supersections */
|
||||||
|
#define TTBSEC_NS 0x00080000 /* Not Secure */
|
||||||
|
#define TTBSEC_ALLFLAGS 0x000FFFFF /* "all flags" mask */
|
||||||
|
#define TTBSEC_BASE 0xFFF00000 /* section base address mask */
|
||||||
|
#define TTBSEC_SBASE 0xFF000000 /* supersection base address mask */
|
||||||
|
#define TTBSEC_SBASEHI 0x00F00000 /* supersection high base address mask */
|
||||||
|
|
||||||
|
/* AP bits for the standard access control model */
|
||||||
|
#define TTBSEC_AP00 0x00000000 /* no access */
|
||||||
|
#define TTBSEC_AP01 0x00000400 /* supervisor only access */
|
||||||
|
#define TTBSEC_AP10 0x00000800 /* user read-only access */
|
||||||
|
#define TTBSEC_AP11 0x00000C00 /* user read-write access */
|
||||||
|
|
||||||
|
/* AP bits for the simplified access control model */
|
||||||
|
#define TTBSEC_ACCESS 0x00000400 /* Accessed bit */
|
||||||
|
#define TTBSEC_AP_PL0 0x00000800 /* enable access at PL0 */
|
||||||
|
#define TTBSEC_AP_RO TTBSEC_APX /* read-only access */
|
||||||
|
|
||||||
|
/* Page table descriptor bits */
|
||||||
|
#define TTBPGTBL_ALWAYS 0x00000001 /* bottom-two bits are always this */
|
||||||
|
#define TTBPGTBL_PXN 0x00000004 /* Privileged Execute-Never */
|
||||||
|
#define TTBPGTBL_NS 0x00000008 /* Not Secure */
|
||||||
|
#define TTBPGTBL_DOM_MASK 0x000001E0 /* domain indicator */
|
||||||
|
#define TTBPGTBL_P 0x00000200 /* ECC enabled (not supported) */
|
||||||
|
#define TTBPGTBL_ALLFLAGS 0x000003FF /* "all flags" mask */
|
||||||
|
#define TTBPGTBL_BASE 0xFFFFFC00 /* page table base address mask */
|
||||||
|
|
||||||
|
/* Bits to query the type of TTB entry we're looking at */
|
||||||
|
#define TTBQUERY_MASK 0x00000003 /* bits we can query */
|
||||||
|
#define TTBQUERY_FAULT 0x00000000 /* indicates a fault */
|
||||||
|
#define TTBQUERY_PGTBL 0x00000001 /* indicates a page table */
|
||||||
|
#define TTBQUERY_SEC 0x00000002 /* indicates a section */
|
||||||
|
#define TTBQUERY_PXNSEC 0x00000003 /* indicates a section with PXN (or reserved) */
|
||||||
|
|
||||||
|
/* Small page table entry bits */
|
||||||
|
#define PGTBLSM_XN 0x00000001 /* Execute-Never */
|
||||||
|
#define PGTBLSM_ALWAYS 0x00000002 /* this bit must always be set for a page table entry */
|
||||||
|
#define PGTBLSM_B 0x00000004 /* memory region attribute bit */
|
||||||
|
#define PGTBLSM_C 0x00000008 /* memory region attribute bit */
|
||||||
|
#define PGTBLSM_AP 0x00000030 /* access permission bits */
|
||||||
|
#define PGTBLSM_TEX 0x000001C0 /* memory type flags */
|
||||||
|
#define PGTBLSM_APX 0x00000200 /* access permission extended */
|
||||||
|
#define PGTBLSM_S 0x00000400 /* Shared */
|
||||||
|
#define PGTBLSM_NG 0x00000800 /* Not Global */
|
||||||
|
#define PGTBLSM_PAGE 0xFFFFF000 /* page base address mask */
|
||||||
|
|
||||||
|
/* AP bits for the standard access control model */
|
||||||
|
#define PGTBLSM_AP00 0x00000000 /* no access */
|
||||||
|
#define PGTBLSM_AP01 0x00000010 /* supervisor only access */
|
||||||
|
#define PGTBLSM_AP10 0x00000020 /* user read-only access */
|
||||||
|
#define PGTBLSM_AP11 0x00000030 /* user read-write access */
|
||||||
|
|
||||||
|
/* Bits to query the type of page table entry we're looking at */
|
||||||
|
#define PGQUERY_MASK 0x00000003 /* bits we can query */
|
||||||
|
#define PGQUERY_FAULT 0x00000000 /* indicates a fault */
|
||||||
|
#define PGQUERY_LG 0x00000001 /* large page (64K) */
|
||||||
|
#define PGQUERY_SM 0x00000002 /* small page (4K) */
|
||||||
|
#define PGQUERY_SM_XN 0x00000003 /* small page with Execute-Never set */
|
||||||
|
|
||||||
|
#ifndef __ASM__
|
||||||
|
|
||||||
|
/*-------------------------------------------------------
|
||||||
|
* Data structures defining the TTB and page table data.
|
||||||
|
*-------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* TTB fault descriptor */
|
||||||
|
typedef struct tagTTBFAULT {
|
||||||
|
unsigned always0 : 2; /* bits are always 0 for a fault entry */
|
||||||
|
unsigned ignored : 30; /* ignored (COMROGUE may define these later) */
|
||||||
|
} TTBFAULT, *PTTBFAULT;
|
||||||
|
|
||||||
|
/* TTB page table descriptor */
|
||||||
|
typedef struct tagTTBPGTBL {
|
||||||
|
unsigned always01 : 2; /* bits are always 01 for a page table */
|
||||||
|
unsigned pxn : 1; /* Privileged Execute-Never bit */
|
||||||
|
unsigned ns : 1; /* Not Secure bit */
|
||||||
|
unsigned always0 : 1; /* bit is always 0 for a page table */
|
||||||
|
unsigned domain : 4; /* protection domain */
|
||||||
|
unsigned p : 1; /* not supported, should be 0 */
|
||||||
|
unsigned baseaddr : 22; /* upper 22 bits of base address of page table */
|
||||||
|
} TTBPGTBL, *PTTBPGTBL;
|
||||||
|
|
||||||
|
/* TTB section descriptor */
|
||||||
|
typedef struct tagTTBSEC {
|
||||||
|
unsigned pxn : 1; /* Privileged Execute-Never bit */
|
||||||
|
unsigned always1: 1; /* bit is always 1 for a section */
|
||||||
|
unsigned b : 1; /* attribute bit ("Buffered") */
|
||||||
|
unsigned c : 1; /* attribute bit ("Cached") */
|
||||||
|
unsigned xn : 1; /* Execute-Never bit */
|
||||||
|
unsigned domain : 4; /* protection domain */
|
||||||
|
unsigned p : 1; /* not supported, should be 0 */
|
||||||
|
unsigned ap : 2; /* access permissions */
|
||||||
|
unsigned tex : 3; /* memory type flags */
|
||||||
|
unsigned ap2 : 1; /* access permission extension */
|
||||||
|
unsigned s : 1; /* Shared bit */
|
||||||
|
unsigned ng : 1; /* Not Global bit */
|
||||||
|
unsigned always0 : 1; /* bit is always 0 for a section */
|
||||||
|
unsigned ns : 1; /* Not Secure bit */
|
||||||
|
unsigned baseaddr : 12; /* upper 12 bits of base address of section */
|
||||||
|
} TTBSEC, *PTTBSEC;
|
||||||
|
|
||||||
|
/* Single TTB entry descriptor */
|
||||||
|
typedef union tagTTB {
|
||||||
|
UINT32 data; /* raw data for entry */
|
||||||
|
TTBFAULT fault; /* "fault" data */
|
||||||
|
TTBPGTBL pgtbl; /* page table data */
|
||||||
|
TTBSEC sec; /* 1Mb section data */
|
||||||
|
} TTB, *PTTB;
|
||||||
|
|
||||||
|
/* page table descriptor for a fault entry */
|
||||||
|
typedef struct tagPGTBLFAULT {
|
||||||
|
unsigned always0 : 2; /* bits are always 0 for a fault entry */
|
||||||
|
unsigned ignored : 30; /* ignored (COMROGUE may define these later) */
|
||||||
|
} PGTBLFAULT, *PPGTBLFAULT;
|
||||||
|
|
||||||
|
/* page table descriptor for regular 4K pages */
|
||||||
|
typedef struct tagPGTBLSM {
|
||||||
|
unsigned xn : 1; /* Execute Never */
|
||||||
|
unsigned always1 : 1; /* always 1 for a 4k small page */
|
||||||
|
unsigned b : 1; /* attribute bit ("Buffered") */
|
||||||
|
unsigned c : 1; /* attribute bit ("Cached") */
|
||||||
|
unsigned ap : 2; /* access permissions */
|
||||||
|
unsigned tex : 3; /* memory type flags */
|
||||||
|
unsigned apx : 1; /* access permission extension */
|
||||||
|
unsigned s : 1; /* Shared bit */
|
||||||
|
unsigned ng : 1; /* Not Global bit */
|
||||||
|
unsigned pgaddr : 20; /* upper 20 bits of base address of page */
|
||||||
|
} PGTBLSM, *PPGTBLSM;
|
||||||
|
|
||||||
|
/* single page table entry */
|
||||||
|
typedef union tagPGTBL {
|
||||||
|
UINT32 data; /* raw data for entry */
|
||||||
|
PGTBLFAULT fault; /* "fault" data */
|
||||||
|
PGTBLSM pg; /* small page descriptor */
|
||||||
|
} PGTBL, *PPGTBL;
|
||||||
|
|
||||||
|
/* page table auxiliary entry */
|
||||||
|
typedef union tagPGAUX {
|
||||||
|
UINT32 data; /* raw data for entry */
|
||||||
|
/* TODO */
|
||||||
|
} PGAUX, *PPGAUX;
|
||||||
|
|
||||||
|
/* complete structure of a page table, hardware + auxiliary */
|
||||||
|
typedef struct tagPAGETAB {
|
||||||
|
PGTBL pgtbl[SYS_PGTBL_ENTRIES]; /* hardware page table entries */
|
||||||
|
PGAUX pgaux[SYS_PGTBL_ENTRIES]; /* auxiliary page table entries */
|
||||||
|
} PAGETAB, *PPAGETAB;
|
||||||
|
|
||||||
|
/* VMA index macros */
|
||||||
|
#define mmVMA2TTBIndex(vma) (((vma) >> (SYS_PAGE_BITS + SYS_PGTBL_BITS)) & ((1 << SYS_TTB_BITS) - 1))
|
||||||
|
#define mmVMA2PGTBLIndex(vma) (((vma) >> SYS_PAGE_BITS) & ((1 << SYS_PGTBL_BITS) - 1))
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Data structures for the Master Page Database.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* internal structure of a MPDB entry */
|
||||||
|
typedef struct tagMPDB1 {
|
||||||
|
unsigned next : 20; /* index of "next" entry in list */
|
||||||
|
unsigned tag : 12; /* page tag */
|
||||||
|
} MPDB1;
|
||||||
|
|
||||||
|
/* The MPDB entry itself. */
|
||||||
|
typedef union tagMPDB {
|
||||||
|
UINT32 raw; /* raw data */
|
||||||
|
MPDB1 d; /* structured data */
|
||||||
|
} MPDB, *PMPDB;
|
||||||
|
|
||||||
|
#endif /* __ASM__ */
|
||||||
|
|
||||||
|
#endif /* __COMROGUE_INTERNALS__ */
|
||||||
|
|
||||||
|
#endif /* __MMU_H_INCLUDED */
|
68
include/comrogue/internals/sctlr.h
Normal file
68
include/comrogue/internals/sctlr.h
Normal file
|
@ -0,0 +1,68 @@
|
||||||
|
/*
|
||||||
|
* This file is part of the COMROGUE Operating System for Raspberry Pi
|
||||||
|
*
|
||||||
|
* Copyright (c) 2013, Eric J. Bowersox / Erbosoft Enterprises
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This program is free for commercial and non-commercial use as long as the following conditions are
|
||||||
|
* adhered to.
|
||||||
|
*
|
||||||
|
* Copyright in this file remains Eric J. Bowersox and/or Erbosoft, and as such any copyright notices
|
||||||
|
* in the code are not to be removed.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification, are permitted
|
||||||
|
* provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* * Redistributions of source code must retain the above copyright notice, this list of conditions and
|
||||||
|
* the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
|
||||||
|
* the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
|
||||||
|
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||||
|
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||||
|
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* "Raspberry Pi" is a trademark of the Raspberry Pi Foundation.
|
||||||
|
*/
|
||||||
|
#ifndef __SCTLR_H_INCLUDED
|
||||||
|
#define __SCTLR_H_INCLUDED
|
||||||
|
|
||||||
|
#ifdef __COMROGUE_INTERNALS__
|
||||||
|
|
||||||
|
/*------------------------------------------------------
|
||||||
|
* Bits in the System Control Register (SCTLR), CP15 c1
|
||||||
|
*------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define SCTLR_M 0x00000001 /* MMU: 1 = enabled, 0 = disabled */
|
||||||
|
#define SCTLR_A 0x00000002 /* Alignment check: 1 = enabled, 0 = disabled */
|
||||||
|
#define SCTLR_C 0x00000004 /* Cache: 1 = enabled, 0 = disabled */
|
||||||
|
#define SCTLR_CP15BEN 0x00000020 /* CP15 barrier operations: 1 = enabled (default), 0 = disabled */
|
||||||
|
#define SCTLR_B 0x00000080 /* Endianness: 0 = default, do not modify */
|
||||||
|
#define SCTLR_SW 0x00000400 /* SWP/SWPB instructions: 0 = disable, 1 = enable */
|
||||||
|
#define SCTLR_Z 0x00000800 /* Branch prediction: 0 = disable, 1 = enable */
|
||||||
|
#define SCTLR_I 0x00001000 /* Instruction cache: 0 = disable, 1 = enable */
|
||||||
|
#define SCTLR_V 0x00002000 /* Exception vectors: 0 = 0x00000000 (configurable), 1 = 0xFFFF0000 (fixed) */
|
||||||
|
#define SCTLR_RR 0x00004000 /* Cache strategy: 0 = normal, 1 = round-robin */
|
||||||
|
#define SCTLR_L4 0x00008000 /* PC load reset T-bit: 0 = yes, 1 = no */
|
||||||
|
#define SCTLR_HA 0x00020000 /* Hardware access flag: 0 = disabled, 1 = enabled */
|
||||||
|
#define SCTLR_WXN 0x00080000 /* Write permission implies XN: 0 = no, 1 = yes */
|
||||||
|
#define SCTLR_UWXN 0x00100000 /* Unprivileged write permission implies PL1 XN: 0 = no, 1 = yes */
|
||||||
|
#define SCTLR_FI 0x00200000 /* Fast interrupts: 0 = normal, 1 = low-latency */
|
||||||
|
#define SCTLR_U 0x00400000 /* unaligned access: 0 = disabled (default), 1 = enabled */
|
||||||
|
#define SCTLR_XP 0x00800000 /* subpage AP bits: 0 = enabled, 1 = disabled */
|
||||||
|
#define SCTLR_VE 0x01000000 /* Interrupt vectors: 0 = standard, 1 = determined by VIC */
|
||||||
|
#define SCTLR_EE 0x02000000 /* Exception endianness: 0 = little-endian (default), 1 = big-endian */
|
||||||
|
#define SCTLR_NMFI 0x08000000 /* Non-maskable FIQ: 0 = disabled, 1 = enabled */
|
||||||
|
#define SCTLR_TRE 0x10000000 /* TEX attributes remap: 0 = disabled, 1 = enabled */
|
||||||
|
#define SCTLR_AFE 0x20000000 /* AP[0] = Access Flag: 0 = disabled, 1 = enabled */
|
||||||
|
#define SCTLR_TE 0x40000000 /* Instruction set state for exceptions: 0 = ARM (default), 1 = Thumb */
|
||||||
|
|
||||||
|
#endif /* __COMROGUE_INTERNALS__ */
|
||||||
|
|
||||||
|
#endif /* __SCTLR_H_INCLUDED */
|
69
include/comrogue/internals/seg.h
Normal file
69
include/comrogue/internals/seg.h
Normal file
|
@ -0,0 +1,69 @@
|
||||||
|
/*
|
||||||
|
* This file is part of the COMROGUE Operating System for Raspberry Pi
|
||||||
|
*
|
||||||
|
* Copyright (c) 2013, Eric J. Bowersox / Erbosoft Enterprises
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This program is free for commercial and non-commercial use as long as the following conditions are
|
||||||
|
* adhered to.
|
||||||
|
*
|
||||||
|
* Copyright in this file remains Eric J. Bowersox and/or Erbosoft, and as such any copyright notices
|
||||||
|
* in the code are not to be removed.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification, are permitted
|
||||||
|
* provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* * Redistributions of source code must retain the above copyright notice, this list of conditions and
|
||||||
|
* the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
|
||||||
|
* the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
|
||||||
|
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||||
|
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||||
|
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* "Raspberry Pi" is a trademark of the Raspberry Pi Foundation.
|
||||||
|
*/
|
||||||
|
#ifndef __SEG_H_INCLUDED
|
||||||
|
#define __SEG_H_INCLUDED
|
||||||
|
|
||||||
|
#ifdef __COMROGUE_INTERNALS__
|
||||||
|
|
||||||
|
#ifndef __ASM__
|
||||||
|
|
||||||
|
#include <comrogue/types.h>
|
||||||
|
|
||||||
|
#ifdef __COMROGUE_PRESTART__
|
||||||
|
|
||||||
|
#define SEG_INIT_CODE __attribute__((__section__(".prestart.text")))
|
||||||
|
#define SEG_INIT_DATA __attribute__((__section__(".prestart.data")))
|
||||||
|
#define SEG_INIT_RODATA __attribute__((__section__(".prestart.rodata")))
|
||||||
|
#define SEG_RODATA SEG_INIT_RODATA
|
||||||
|
#define SEG_LIB_CODE SEG_INIT_CODE
|
||||||
|
#define SEG_LIB_RODATA SEG_INIT_RODATA
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#define SEG_INIT_CODE __attribute__((__section__(".init.text")))
|
||||||
|
#define SEG_INIT_DATA __attribute__((__section__(".init.data")))
|
||||||
|
#define SEG_INIT_RODATA __attribute__((__section__(".init.rodata")))
|
||||||
|
#define SEG_RODATA __attribute__((__section__(".rodata")))
|
||||||
|
#define SEG_LIB_CODE __attribute__((__section__(".lib.text")))
|
||||||
|
#define SEG_LIB_RODATA __attribute__((__section__(".lib.rodata")))
|
||||||
|
|
||||||
|
#endif /* __COMROGUE_PRESTART__ */
|
||||||
|
|
||||||
|
#define DECLARE_INIT_STRING8_CONST(name, value) const CHAR SEG_INIT_RODATA name [] = value
|
||||||
|
#define DECLARE_LIB_STRING8_CONST(name, value) const CHAR SEG_LIB_RODATA name [] = value
|
||||||
|
#define DECLARE_STRING8_CONST(name, value) const CHAR SEG_RODATA name [] = value
|
||||||
|
|
||||||
|
#endif /* __ASM__ */
|
||||||
|
|
||||||
|
#endif /* __COMROGUE_INTERNALS__ */
|
||||||
|
|
||||||
|
#endif /* __SEG_H_INCLUDED */
|
200
include/comrogue/internals/startup.h
Normal file
200
include/comrogue/internals/startup.h
Normal file
|
@ -0,0 +1,200 @@
|
||||||
|
/*
|
||||||
|
* This file is part of the COMROGUE Operating System for Raspberry Pi
|
||||||
|
*
|
||||||
|
* Copyright (c) 2013, Eric J. Bowersox / Erbosoft Enterprises
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This program is free for commercial and non-commercial use as long as the following conditions are
|
||||||
|
* adhered to.
|
||||||
|
*
|
||||||
|
* Copyright in this file remains Eric J. Bowersox and/or Erbosoft, and as such any copyright notices
|
||||||
|
* in the code are not to be removed.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification, are permitted
|
||||||
|
* provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* * Redistributions of source code must retain the above copyright notice, this list of conditions and
|
||||||
|
* the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
|
||||||
|
* the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
|
||||||
|
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||||
|
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||||
|
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* "Raspberry Pi" is a trademark of the Raspberry Pi Foundation.
|
||||||
|
*/
|
||||||
|
#ifndef __STARTUP_H_INCLUDED
|
||||||
|
#define __STARTUP_H_INCLUDED
|
||||||
|
|
||||||
|
#ifdef __COMROGUE_INTERNALS__
|
||||||
|
|
||||||
|
#ifdef __COMROGUE_PRESTART__
|
||||||
|
|
||||||
|
/*------------------------------------------------
|
||||||
|
* ATAG data passed to the kernel at startup time
|
||||||
|
*------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* The different ATAG types. */
|
||||||
|
#define ATAGTYPE_NONE 0 /* none - end of list */
|
||||||
|
#define ATAGTYPE_CORE 0x54410001 /* core - this one must be first */
|
||||||
|
#define ATAGTYPE_MEM 0x54410002 /* memory */
|
||||||
|
#define ATAGTYPE_VIDEOTEXT 0x54410003 /* text-mode video */
|
||||||
|
#define ATAGTYPE_RAMDISK 0x54410004 /* RAM disk */
|
||||||
|
#define ATAGTYPE_INITRD2 0x54420005 /* compressed initial RAM disk */
|
||||||
|
#define ATAGTYPE_SERIAL 0x54410006 /* serial number */
|
||||||
|
#define ATAGTYPE_REVISION 0x54410007 /* revision */
|
||||||
|
#define ATAGTYPE_VIDEOLFB 0x54410008 /* linear framebuffer video */
|
||||||
|
#define ATAGTYPE_CMDLINE 0x54410009 /* command line */
|
||||||
|
|
||||||
|
/* Flags for the core ATAG's uiFlags member. */
|
||||||
|
#define ATAG_COREFLAG_READONLY 0x00000001 /* read only */
|
||||||
|
|
||||||
|
#define ATAG_RAMDISKFLAG_LOAD 0x00000001
|
||||||
|
#define ATAG_RAMDISKFLAG_PROMPT 0x00000002
|
||||||
|
|
||||||
|
#endif /* __COMROGUE_PRESTART__ */
|
||||||
|
|
||||||
|
#ifndef __ASM__
|
||||||
|
|
||||||
|
#include <comrogue/types.h>
|
||||||
|
|
||||||
|
#ifdef __COMROGUE_PRESTART__
|
||||||
|
|
||||||
|
/* Header of all ATAGs. */
|
||||||
|
typedef struct tagATAG_HEADER {
|
||||||
|
UINT32 uiSize; /* size of the tag, in 32-bit words */
|
||||||
|
UINT32 uiTag; /* the tag indicator */
|
||||||
|
} ATAG_HEADER, *PATAG_HEADER;
|
||||||
|
|
||||||
|
/* Core ATAG - must be first in the list */
|
||||||
|
typedef struct tagATAG_CORE {
|
||||||
|
ATAG_HEADER hdr; /* header */
|
||||||
|
UINT32 uiFlags; /* core flags, see above */
|
||||||
|
UINT32 uiPageSize; /* system page size in bytes */
|
||||||
|
UINT32 uiRootDevice; /* root device number */
|
||||||
|
} ATAG_CORE, *PATAG_CORE;
|
||||||
|
|
||||||
|
/* Memory ATAG */
|
||||||
|
typedef struct tagATAG_MEM {
|
||||||
|
ATAG_HEADER hdr; /* header */
|
||||||
|
UINT32 uiSize; /* size of memory */
|
||||||
|
PHYSADDR paStart; /* physical address of start of memory */
|
||||||
|
} ATAG_MEM, *PATAG_MEM;
|
||||||
|
|
||||||
|
/* Text-mode video ATAG */
|
||||||
|
typedef struct tagATAG_VIDEOTEXT {
|
||||||
|
ATAG_HEADER hdr; /* header */
|
||||||
|
BYTE bWidth; /* display width */
|
||||||
|
BYTE bHeight; /* display height */
|
||||||
|
UINT16 uiVideoPage;
|
||||||
|
BYTE bVideoMode;
|
||||||
|
BYTE bColumns;
|
||||||
|
UINT16 uiEGABX;
|
||||||
|
BYTE bLines;
|
||||||
|
BYTE bIsVGA;
|
||||||
|
UINT16 uiPoints;
|
||||||
|
} ATAG_VIDEOTEXT, *PATAG_VIDEOTEXT;
|
||||||
|
|
||||||
|
/* RAM disk ATAG */
|
||||||
|
typedef struct tagATAG_RAMDISK {
|
||||||
|
ATAG_HEADER hdr; /* header */
|
||||||
|
UINT32 uiFlags; /* RAM disk flags, see above */
|
||||||
|
UINT32 uiSize; /* size of ramdisk in kB */
|
||||||
|
UINT32 uiStartBlock; /* starting block of ramdisk */
|
||||||
|
} ATAG_RAMDISK, *PATAG_RAMDISK;
|
||||||
|
|
||||||
|
/* Initial ramdisk image ATAG */
|
||||||
|
typedef struct tagATAG_INITRD2 {
|
||||||
|
ATAG_HEADER hdr; /* header */
|
||||||
|
PHYSADDR paStart; /* physical address of compressed ramdisk image */
|
||||||
|
UINT32 uiSize; /* size of compressed ramdisk image in bytes */
|
||||||
|
} ATAG_INITRD2, *PATAG_INITRD2;
|
||||||
|
|
||||||
|
/* Serial number ATAG */
|
||||||
|
typedef struct tagATAG_SERIAL {
|
||||||
|
ATAG_HEADER hdr; /* header */
|
||||||
|
UINT32 uiSerialNumberLow; /* low word of serial number */
|
||||||
|
UINT32 uiSerialNumberHigh; /* high word of serial number */
|
||||||
|
} ATAG_SERIAL, *PATAG_SERIAL;
|
||||||
|
|
||||||
|
/* Revision number ATAG */
|
||||||
|
typedef struct tagATAG_REVISION {
|
||||||
|
ATAG_HEADER hdr; /* header */
|
||||||
|
UINT32 uiRevision; /* revision number */
|
||||||
|
} ATAG_REVISION, *PATAG_REVISION;
|
||||||
|
|
||||||
|
/* Linear framebuffer video ATAG */
|
||||||
|
typedef struct tagATAG_VIDEOLFB {
|
||||||
|
ATAG_HEADER hdr; /* header */
|
||||||
|
UINT16 uiFrameBufferWidth;
|
||||||
|
UINT16 uiFrameBufferHeight;
|
||||||
|
UINT16 uiFrameBufferDepth;
|
||||||
|
UINT16 uiFrameBufferLineLength;
|
||||||
|
UINT32 uiFrameBufferBase;
|
||||||
|
UINT32 uiFrameBufferSize;
|
||||||
|
BYTE bRedSize;
|
||||||
|
BYTE bRedPos;
|
||||||
|
BYTE bGreenSize;
|
||||||
|
BYTE bGreenPos;
|
||||||
|
BYTE bBlueSize;
|
||||||
|
BYTE bBluePos;
|
||||||
|
BYTE bReservedSize;
|
||||||
|
BYTE bReservedPos;
|
||||||
|
} ATAG_VIDEOLFB, *PATAG_VIDEOLFB;
|
||||||
|
|
||||||
|
/* Command line ATAG */
|
||||||
|
typedef struct tagATAG_CMDLINE {
|
||||||
|
ATAG_HEADER hdr; /* header */
|
||||||
|
CHAR szCommandLine[1]; /* text of command line, null-terminated */
|
||||||
|
} ATAG_CMDLINE, *PATAG_CMDLINE;
|
||||||
|
|
||||||
|
/* Macro to advance to the next ATAG */
|
||||||
|
#define kiNextATAG(p) ((PATAG_HEADER)(((PUINT32)(p)) + ((PATAG_HEADER)(p))->uiSize))
|
||||||
|
|
||||||
|
#endif /* __COMROGUE_PRESTART__ */
|
||||||
|
|
||||||
|
/*----------------------------------------------------------------
|
||||||
|
* The startup information buffer filled in by the prestart code.
|
||||||
|
*----------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
typedef struct tagSTARTUP_INFO {
|
||||||
|
/* start of structure accessed from ASM - be careful here */
|
||||||
|
UINT32 cb; /* number of bytes in this structure */
|
||||||
|
PHYSADDR paTTB; /* physical address of the TTB */
|
||||||
|
KERNADDR kaTTB; /* kernel address of the TTB */
|
||||||
|
/* end of structure accessed from ASM - be careful here */
|
||||||
|
UINT32 uiMachineType; /* machine type indicator */
|
||||||
|
UINT32 uiRevision; /* board revision */
|
||||||
|
UINT32 uiSerialNumber; /* serial number */
|
||||||
|
UINT32 cpgSystemTotal; /* total number of memory pages in the system */
|
||||||
|
UINT32 cpgSystemAvail; /* available memory pages in the system after GPU takes its bite */
|
||||||
|
UINT32 cpgTTBGap; /* number of pages in the "gap" between the end of kernel and TTB */
|
||||||
|
PHYSADDR paMPDB; /* physical address of the Master Page Database */
|
||||||
|
KERNADDR kaMPDB; /* kernel address of the Master Page Database */
|
||||||
|
UINT32 cpgMPDB; /* number of pages we allocated for Master Page Database */
|
||||||
|
PHYSADDR paFirstPageTable; /* physical address of the first page table */
|
||||||
|
UINT32 cpgPageTables; /* number of pages we allocated for page tables */
|
||||||
|
UINT32 ctblFreeOnLastPage; /* number of page tables free on last page (0 or 1) */
|
||||||
|
PHYSADDR paFirstFree; /* first free physical address after initial page tables */
|
||||||
|
KERNADDR vmaFirstFree; /* first free virtual memory address after mapped TTB */
|
||||||
|
UINT32 uiEMMCClockFreq; /* EMMC clock frequency */
|
||||||
|
PHYSADDR paVCMem; /* VideoCore memory base */
|
||||||
|
UINT32 cbVCMem; /* VideoCore memory size in bytes */
|
||||||
|
UINT16 cxFBWidth; /* frame buffer width in pixels */
|
||||||
|
UINT16 cyFBHeight; /* frame buffer height in pixels */
|
||||||
|
BYTE abMACAddress[6]; /* MAC address of the network interface */
|
||||||
|
} STARTUP_INFO, *PSTARTUP_INFO;
|
||||||
|
|
||||||
|
#endif /* __ASM__ */
|
||||||
|
|
||||||
|
#endif /* __COMROGUE_INTERNALS__ */
|
||||||
|
|
||||||
|
#endif /* __STARTUP_H_INCLUDED */
|
112
include/comrogue/internals/trace.h
Normal file
112
include/comrogue/internals/trace.h
Normal file
|
@ -0,0 +1,112 @@
|
||||||
|
/*
|
||||||
|
* This file is part of the COMROGUE Operating System for Raspberry Pi
|
||||||
|
*
|
||||||
|
* Copyright (c) 2013, Eric J. Bowersox / Erbosoft Enterprises
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This program is free for commercial and non-commercial use as long as the following conditions are
|
||||||
|
* adhered to.
|
||||||
|
*
|
||||||
|
* Copyright in this file remains Eric J. Bowersox and/or Erbosoft, and as such any copyright notices
|
||||||
|
* in the code are not to be removed.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification, are permitted
|
||||||
|
* provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* * Redistributions of source code must retain the above copyright notice, this list of conditions and
|
||||||
|
* the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
|
||||||
|
* the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
|
||||||
|
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||||
|
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||||
|
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* "Raspberry Pi" is a trademark of the Raspberry Pi Foundation.
|
||||||
|
*/
|
||||||
|
#ifndef __TRACE_H_INCLUDED
|
||||||
|
#define __TRACE_H_INCLUDED
|
||||||
|
|
||||||
|
#ifdef __COMROGUE_INTERNALS__
|
||||||
|
|
||||||
|
#ifndef __ASM__
|
||||||
|
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <comrogue/types.h>
|
||||||
|
#include <comrogue/scode.h>
|
||||||
|
#include <comrogue/compiler_macros.h>
|
||||||
|
#include <comrogue/internals/seg.h>
|
||||||
|
|
||||||
|
/*------------------------
|
||||||
|
* System trace functions
|
||||||
|
*------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
CDECL_BEGIN
|
||||||
|
|
||||||
|
#ifdef __COMROGUE_PRESTART__
|
||||||
|
|
||||||
|
extern void ETrInit(void);
|
||||||
|
extern void ETrWriteChar8(CHAR c);
|
||||||
|
extern void ETrWriteString8(PCSTR psz);
|
||||||
|
extern void ETrWriteWord(UINT32 uiValue);
|
||||||
|
extern void ETrDumpWords(PUINT32 puiWords, UINT32 cWords);
|
||||||
|
extern void ETrAssertFailed(PCSTR pszFile, INT32 nLine);
|
||||||
|
extern void ETrInfiniBlink(void);
|
||||||
|
|
||||||
|
#define ASSERT_FAIL_FUNC ETrAssertFailed
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
extern void TrInit(void);
|
||||||
|
extern void TrWriteChar8(CHAR c);
|
||||||
|
extern void TrWriteString8(PCSTR str);
|
||||||
|
extern void TrWriteWord(UINT32 uiValue);
|
||||||
|
extern HRESULT TrVPrintf8(PCSTR pszFormat, va_list pargs);
|
||||||
|
extern HRESULT TrPrintf8(PCSTR pszFormat, ...);
|
||||||
|
extern void TrAssertFailed(PCSTR pszFile, INT32 nLine);
|
||||||
|
extern void TrInfiniBlink(void);
|
||||||
|
|
||||||
|
#define ASSERT_FAIL_FUNC TrAssertFailed
|
||||||
|
|
||||||
|
#endif /* __COMROGUE_PRESTART__ */
|
||||||
|
|
||||||
|
CDECL_END
|
||||||
|
|
||||||
|
/*------------------------------------------------
|
||||||
|
* Macro definitions for the assert functionality
|
||||||
|
*------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef NDEBUG
|
||||||
|
|
||||||
|
#define THIS_FILE __FILE__
|
||||||
|
|
||||||
|
#if defined(__COMROGUE_PRESTART__) || defined(__COMROGUE_INIT__)
|
||||||
|
#define DECLARE_THIS_FILE static DECLARE_INIT_STRING8_CONST(THIS_FILE, __FILE__);
|
||||||
|
#else
|
||||||
|
#define DECLARE_THIS_FILE static DECLARE_STRING8_CONST(THIS_FILE, __FILE__);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define ASSERT(x) ((x) ? (void)0 : ASSERT_FAIL_FUNC(THIS_FILE, __LINE__))
|
||||||
|
#define VERIFY(x) ASSERT(x)
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#define DECLARE_THIS_FILE
|
||||||
|
|
||||||
|
#define ASSERT(x) ((void)0)
|
||||||
|
#define VERIFY(x) ((void)(x))
|
||||||
|
|
||||||
|
#endif /* NDEBUG */
|
||||||
|
|
||||||
|
#endif /* __ASM__ */
|
||||||
|
|
||||||
|
#endif /* __COMROGUE_INTERNALS__ */
|
||||||
|
|
||||||
|
#endif /* __TRACE_H_INCLUDED */
|
57
include/comrogue/intlib.h
Normal file
57
include/comrogue/intlib.h
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
/*
|
||||||
|
* This file is part of the COMROGUE Operating System for Raspberry Pi
|
||||||
|
*
|
||||||
|
* Copyright (c) 2013, Eric J. Bowersox / Erbosoft Enterprises
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This program is free for commercial and non-commercial use as long as the following conditions are
|
||||||
|
* adhered to.
|
||||||
|
*
|
||||||
|
* Copyright in this file remains Eric J. Bowersox and/or Erbosoft, and as such any copyright notices
|
||||||
|
* in the code are not to be removed.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification, are permitted
|
||||||
|
* provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* * Redistributions of source code must retain the above copyright notice, this list of conditions and
|
||||||
|
* the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
|
||||||
|
* the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
|
||||||
|
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||||
|
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||||
|
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* "Raspberry Pi" is a trademark of the Raspberry Pi Foundation.
|
||||||
|
*/
|
||||||
|
#ifndef __INTLIB_H_INCLUDED
|
||||||
|
#define __INTLIB_H_INCLUDED
|
||||||
|
|
||||||
|
#ifndef __ASM__
|
||||||
|
|
||||||
|
#include <comrogue/types.h>
|
||||||
|
#include <comrogue/scode.h>
|
||||||
|
#include <comrogue/compiler_macros.h>
|
||||||
|
|
||||||
|
#define intMin(x, y) (((x) < (y)) ? (x) : (y))
|
||||||
|
#define intMax(x, y) (((x) > (y)) ? (x) : (y))
|
||||||
|
|
||||||
|
typedef struct tagLDIV {
|
||||||
|
INT64 quot;
|
||||||
|
INT64 rem;
|
||||||
|
} LDIV, *PLDIV;
|
||||||
|
|
||||||
|
CDECL_BEGIN
|
||||||
|
|
||||||
|
extern HRESULT IntLDiv(PLDIV pResult, INT64 num, INT64 denom);
|
||||||
|
|
||||||
|
CDECL_END
|
||||||
|
|
||||||
|
#endif /* __ASM__ */
|
||||||
|
|
||||||
|
#endif /* __INTLIB_H_INCLUDED */
|
90
include/comrogue/object_definition_macros.h
Normal file
90
include/comrogue/object_definition_macros.h
Normal file
|
@ -0,0 +1,90 @@
|
||||||
|
#ifndef __OBJECT_DEFINITION_MACROS_H_INCLUDED
|
||||||
|
#define __OBJECT_DEFINITION_MACROS_H_INCLUDED
|
||||||
|
|
||||||
|
#ifndef __ASM__
|
||||||
|
|
||||||
|
#include <comrogue/compiler_macros.h>
|
||||||
|
#include <comrogue/types.h>
|
||||||
|
|
||||||
|
/*------------------------------------------------------------------------------------
|
||||||
|
* GUID definition macros which define either a GUID or an external reference to one,
|
||||||
|
* controlled by symbol INITGUID
|
||||||
|
*------------------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
#ifndef GUIDATTR
|
||||||
|
#ifdef __COMROGUE_INTERNALS__
|
||||||
|
#include <comrogue/internals/seg.h>
|
||||||
|
#define GUIDATTR SEG_RODATA
|
||||||
|
#else
|
||||||
|
#define GUIDATTR
|
||||||
|
#endif /* __COMROGUE_INTERNALS__ */
|
||||||
|
#endif /* GUIDATTR */
|
||||||
|
|
||||||
|
#ifdef INITGUID
|
||||||
|
|
||||||
|
#define DEFINE_UUID_TYPE(typ, name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \
|
||||||
|
EXTERN_C const typ GUIDATTR name = { l, w1, w2, { b1, b2, b3, b4, b5, b6, b7, b8 } }
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#define DEFINE_UUID_TYPE(typ, name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \
|
||||||
|
EXTERN_C extern const typ GUIDATTR name
|
||||||
|
|
||||||
|
#endif /* INITGUID */
|
||||||
|
|
||||||
|
#define DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \
|
||||||
|
DEFINE_UUID_TYPE(GUID, name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8)
|
||||||
|
#define DEFINE_IID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \
|
||||||
|
DEFINE_UUID_TYPE(IID, name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8)
|
||||||
|
#define DEFINE_CLSID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \
|
||||||
|
DEFINE_UUID_TYPE(CLSID, name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8)
|
||||||
|
|
||||||
|
/*----------------------------------------------------------------------------------------
|
||||||
|
* Macros used in the auto-generated object declarations, controlled by symbol CINTERFACE
|
||||||
|
*----------------------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if !defined(__cplusplus) && !defined(CINTERFACE)
|
||||||
|
#define CINTERFACE
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define interface struct
|
||||||
|
|
||||||
|
#ifdef CINTERFACE
|
||||||
|
|
||||||
|
#define STDMETHOD_(name, typ) typ (*name)
|
||||||
|
#define STDMETHOD(name) HRESULT (*name)
|
||||||
|
#define THIS_(typ) typ *pThis,
|
||||||
|
#define THIS(typ) typ *pThis
|
||||||
|
#define PURE
|
||||||
|
#define END_METHODS
|
||||||
|
#define INHERIT_METHODS(sym) sym
|
||||||
|
|
||||||
|
#define BEGIN_INTERFACE(typ) \
|
||||||
|
struct typ ## VTable {
|
||||||
|
#define BEGIN_INTERFACE_(typ, parent) \
|
||||||
|
struct typ ## VTable {
|
||||||
|
#define END_INTERFACE(typ) }; \
|
||||||
|
typedef interface typ { const struct typ ## VTable *pVTable; } typ;
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#define STDMETHOD_(name, typ) typ name
|
||||||
|
#define STDMETHOD(name) HRESULT name
|
||||||
|
#define THIS_(typ)
|
||||||
|
#define THIS(typ)
|
||||||
|
#define PURE = 0
|
||||||
|
#define END_METHODS
|
||||||
|
#define INHERIT_METHODS(sym)
|
||||||
|
|
||||||
|
#define BEGIN_INTERFACE(typ) \
|
||||||
|
interface typ {
|
||||||
|
#define BEGIN_INTERFACE_(typ, parent) \
|
||||||
|
interface typ : parent {
|
||||||
|
#define END_INTERFACE(typ) };
|
||||||
|
|
||||||
|
#endif /* CINTERFACE */
|
||||||
|
|
||||||
|
#endif /* __ASM__ */
|
||||||
|
|
||||||
|
#endif /* __OBJECT_DEFINITION_MACROS_H_INCLUDED */
|
97
include/comrogue/scode.h
Normal file
97
include/comrogue/scode.h
Normal file
|
@ -0,0 +1,97 @@
|
||||||
|
/*
|
||||||
|
* This file is part of the COMROGUE Operating System for Raspberry Pi
|
||||||
|
*
|
||||||
|
* Copyright (c) 2013, Eric J. Bowersox / Erbosoft Enterprises
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This program is free for commercial and non-commercial use as long as the following conditions are
|
||||||
|
* adhered to.
|
||||||
|
*
|
||||||
|
* Copyright in this file remains Eric J. Bowersox and/or Erbosoft, and as such any copyright notices
|
||||||
|
* in the code are not to be removed.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification, are permitted
|
||||||
|
* provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* * Redistributions of source code must retain the above copyright notice, this list of conditions and
|
||||||
|
* the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
|
||||||
|
* the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
|
||||||
|
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||||
|
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||||
|
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* "Raspberry Pi" is a trademark of the Raspberry Pi Foundation.
|
||||||
|
*/
|
||||||
|
#ifndef __SCODE_H_INCLUDED
|
||||||
|
#define __SCODE_H_INCLUDED
|
||||||
|
|
||||||
|
#include <comrogue/types.h>
|
||||||
|
|
||||||
|
/*-------------------------------------------------------------------
|
||||||
|
* Status codes are defined as follows:
|
||||||
|
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||||
|
* |S| Facility | Code |
|
||||||
|
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||||
|
* 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 9 8 7 6 5 4 3 2 1 0
|
||||||
|
* 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
|
||||||
|
*
|
||||||
|
* S = Severity: 0 = success, 1 = error
|
||||||
|
* Facility = Facility code
|
||||||
|
* Code = Specific error code
|
||||||
|
*-------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Severity codes */
|
||||||
|
#define SEVERITY_SUCCESS 0x00000000
|
||||||
|
#define SEVERITY_ERROR 0x80000000
|
||||||
|
|
||||||
|
/* Facility codes - compatible with M$ */
|
||||||
|
#define FACILITY_NULL 0
|
||||||
|
#define FACILITY_STORAGE 3
|
||||||
|
#define FACILITY_ITF 4
|
||||||
|
#define FACILITY_COMROGUE 7
|
||||||
|
#define FACILITY_STRFORMAT 0x333
|
||||||
|
|
||||||
|
#ifndef __ASM__
|
||||||
|
|
||||||
|
#include <comrogue/types.h>
|
||||||
|
|
||||||
|
#define SUCCEEDED(s) (((s) & SEVERITY_ERROR) == 0)
|
||||||
|
#define FAILED(s) (((s) & SEVERITY_ERROR) != 0)
|
||||||
|
|
||||||
|
#define SCODE_FACILITY(s) (((s) >> 16) & 0x7FFF)
|
||||||
|
#define SCODE_CODE(s) ((s) & 0xFFFF)
|
||||||
|
|
||||||
|
#define MAKE_SCODE(sev, fac, err) ((SCODE)((sev) | (((fac) & 0x7FFF) << 16) | ((err) & 0xFFFF)))
|
||||||
|
|
||||||
|
#define SCODE_CAST(x) ((SCODE)(x))
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#define SCODE_CAST(x) x
|
||||||
|
|
||||||
|
#endif /* __ASM__ */
|
||||||
|
|
||||||
|
#define S_OK SCODE_CAST(0x00000000) /* OK return */
|
||||||
|
#define S_FALSE SCODE_CAST(0x00000001) /* "False" return */
|
||||||
|
|
||||||
|
#define E_NOTIMPL SCODE_CAST(0x80000001) /* not implemented */
|
||||||
|
#define E_OUTOFMEMORY SCODE_CAST(0x80000002) /* out of memory */
|
||||||
|
#define E_INVALIDARG SCODE_CAST(0x80000003) /* invalid argument */
|
||||||
|
#define E_NOINTERFACE SCODE_CAST(0x80000004) /* no such interface */
|
||||||
|
#define E_POINTER SCODE_CAST(0x80000005) /* invalid pointer */
|
||||||
|
#define E_HANDLE SCODE_CAST(0x80000006) /* invalid handle */
|
||||||
|
#define E_ABORT SCODE_CAST(0x80000007) /* aborted operation */
|
||||||
|
#define E_FAIL SCODE_CAST(0x80000008) /* unspecified failure */
|
||||||
|
#define E_ACCESSDENIED SCODE_CAST(0x80000009) /* access denied */
|
||||||
|
#define E_PENDING SCODE_CAST(0x8000000A) /* data not yet available */
|
||||||
|
#define E_UNEXPECTED SCODE_CAST(0x8000FFFF) /* unexpected error */
|
||||||
|
|
||||||
|
#endif /* __SCODE_H_INCLUDED */
|
62
include/comrogue/str.h
Normal file
62
include/comrogue/str.h
Normal file
|
@ -0,0 +1,62 @@
|
||||||
|
/*
|
||||||
|
* This file is part of the COMROGUE Operating System for Raspberry Pi
|
||||||
|
*
|
||||||
|
* Copyright (c) 2013, Eric J. Bowersox / Erbosoft Enterprises
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This program is free for commercial and non-commercial use as long as the following conditions are
|
||||||
|
* adhered to.
|
||||||
|
*
|
||||||
|
* Copyright in this file remains Eric J. Bowersox and/or Erbosoft, and as such any copyright notices
|
||||||
|
* in the code are not to be removed.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification, are permitted
|
||||||
|
* provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* * Redistributions of source code must retain the above copyright notice, this list of conditions and
|
||||||
|
* the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
|
||||||
|
* the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
|
||||||
|
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||||
|
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||||
|
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* "Raspberry Pi" is a trademark of the Raspberry Pi Foundation.
|
||||||
|
*/
|
||||||
|
#ifndef __STR_H_INCLUDED
|
||||||
|
#define __STR_H_INCLUDED
|
||||||
|
|
||||||
|
#ifndef __ASM__
|
||||||
|
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <comrogue/types.h>
|
||||||
|
#include <comrogue/scode.h>
|
||||||
|
#include <comrogue/compiler_macros.h>
|
||||||
|
|
||||||
|
/*------------------
|
||||||
|
* String functions
|
||||||
|
*------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
typedef HRESULT (*PFNFORMAT8)(PPVOID, PCCHAR, UINT32);
|
||||||
|
|
||||||
|
CDECL_BEGIN
|
||||||
|
|
||||||
|
extern PVOID StrCopyMem(PVOID pDest, PCVOID pSrc, INT32 nBytes);
|
||||||
|
|
||||||
|
extern BOOL StrIsDigit8(CHAR ch);
|
||||||
|
extern INT32 StrLength8(PCSTR psz);
|
||||||
|
extern PCHAR StrChar8(PCSTR psz, INT32 ch);
|
||||||
|
extern HRESULT StrFormatV8(PFNFORMAT8 pfnFormat, PVOID pArg, PCSTR pszFormat, va_list pargs);
|
||||||
|
|
||||||
|
CDECL_END
|
||||||
|
|
||||||
|
#endif /* __ASM__ */
|
||||||
|
|
||||||
|
#endif /* __STR_H_INCLUDED */
|
96
include/comrogue/types.h
Normal file
96
include/comrogue/types.h
Normal file
|
@ -0,0 +1,96 @@
|
||||||
|
/*
|
||||||
|
* This file is part of the COMROGUE Operating System for Raspberry Pi
|
||||||
|
*
|
||||||
|
* Copyright (c) 2013, Eric J. Bowersox / Erbosoft Enterprises
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This program is free for commercial and non-commercial use as long as the following conditions are
|
||||||
|
* adhered to.
|
||||||
|
*
|
||||||
|
* Copyright in this file remains Eric J. Bowersox and/or Erbosoft, and as such any copyright notices
|
||||||
|
* in the code are not to be removed.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification, are permitted
|
||||||
|
* provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* * Redistributions of source code must retain the above copyright notice, this list of conditions and
|
||||||
|
* the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
|
||||||
|
* the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
|
||||||
|
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||||
|
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||||
|
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* "Raspberry Pi" is a trademark of the Raspberry Pi Foundation.
|
||||||
|
*/
|
||||||
|
#ifndef __TYPES_H_INCLUDED
|
||||||
|
#define __TYPES_H_INCLUDED
|
||||||
|
|
||||||
|
/* Integral limit values */
|
||||||
|
#define INT16_MIN 0x8000
|
||||||
|
#define INT16_MAX 0x7FFF
|
||||||
|
#define UINT16_MIN 0
|
||||||
|
#define UINT16_MAX 0xFFFF
|
||||||
|
#define INT32_MIN 0x80000000
|
||||||
|
#define INT32_MAX 0x7FFFFFFF
|
||||||
|
#define UINT32_MIN 0
|
||||||
|
#define UINT32_MAX 0xFFFFFFFF
|
||||||
|
#define INT64_MIN 0x8000000000000000
|
||||||
|
#define INT64_MAX 0x7FFFFFFFFFFFFFFF
|
||||||
|
#define UINT64_MIN 0
|
||||||
|
#define UINT64_MAX 0xFFFFFFFFFFFFFFFF
|
||||||
|
|
||||||
|
#define INT_PTR_MIN INT32_MIN
|
||||||
|
#define INT_PTR_MAX INT32_MAX
|
||||||
|
#define UINT_PTR_MIN UINT32_MIN
|
||||||
|
#define UINT_PTR_MAX UINT32_MAX
|
||||||
|
|
||||||
|
/* Number of bits */
|
||||||
|
#define INT16_BITS 16
|
||||||
|
#define UINT16_BITS 16
|
||||||
|
#define INT32_BITS 32
|
||||||
|
#define UINT32_BITS 32
|
||||||
|
#define INT64_BITS 64
|
||||||
|
#define UINT64_BITS 64
|
||||||
|
|
||||||
|
/* Boolean values */
|
||||||
|
#define TRUE 1
|
||||||
|
#define FALSE 0
|
||||||
|
|
||||||
|
/* NULL value */
|
||||||
|
#ifndef NULL
|
||||||
|
#define NULL 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef __ASM__
|
||||||
|
|
||||||
|
/* The basic types referenced by object_types.h. */
|
||||||
|
typedef unsigned char uint8_t;
|
||||||
|
typedef short int16_t;
|
||||||
|
typedef unsigned short uint16_t;
|
||||||
|
typedef int int32_t;
|
||||||
|
typedef unsigned int uint32_t;
|
||||||
|
typedef long long int64_t;
|
||||||
|
typedef unsigned long long uint64_t;
|
||||||
|
|
||||||
|
#include <comrogue/object_types.h>
|
||||||
|
|
||||||
|
#define MAKEBOOL(val) ((val) ? TRUE : FALSE)
|
||||||
|
|
||||||
|
#ifdef __COMROGUE_INTERNALS__
|
||||||
|
|
||||||
|
/* Internal system types */
|
||||||
|
typedef UINT32 PHYSADDR; /* physical address */
|
||||||
|
typedef UINT32 KERNADDR; /* kernel address */
|
||||||
|
|
||||||
|
#endif /* __COMROGUE_INTERNALS__ */
|
||||||
|
|
||||||
|
#endif /* __ASM__ */
|
||||||
|
|
||||||
|
#endif /* __TYPES_H_INCLUDED */
|
77
kernel/Makefile
Normal file
77
kernel/Makefile
Normal file
|
@ -0,0 +1,77 @@
|
||||||
|
#
|
||||||
|
# This file is part of the COMROGUE Operating System for Raspberry Pi
|
||||||
|
#
|
||||||
|
# Copyright (c) 2013, Eric J. Bowersox / Erbosoft Enterprises
|
||||||
|
# All rights reserved.
|
||||||
|
#
|
||||||
|
# This program is free for commercial and non-commercial use as long as the following conditions are
|
||||||
|
# adhered to.
|
||||||
|
#
|
||||||
|
# Copyright in this file remains Eric J. Bowersox and/or Erbosoft, and as such any copyright notices
|
||||||
|
# in the code are not to be removed.
|
||||||
|
#
|
||||||
|
# Redistribution and use in source and binary forms, with or without modification, are permitted
|
||||||
|
# provided that the following conditions are met:
|
||||||
|
#
|
||||||
|
# * Redistributions of source code must retain the above copyright notice, this list of conditions and
|
||||||
|
# the following disclaimer.
|
||||||
|
# * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
|
||||||
|
# the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||||
|
#
|
||||||
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
|
||||||
|
# WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||||
|
# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||||
|
# TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
# POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
#
|
||||||
|
# "Raspberry Pi" is a trademark of the Raspberry Pi Foundation.
|
||||||
|
|
||||||
|
MAKEFLAGS += -rR
|
||||||
|
|
||||||
|
ARMDIR ?= /opt/gnuarm/bin
|
||||||
|
ARMPREFIX ?= arm-none-eabi
|
||||||
|
CC = $(ARMDIR)/$(ARMPREFIX)-gcc
|
||||||
|
CPP = $(ARMDIR)/$(ARMPREFIX)-cpp
|
||||||
|
AS = $(ARMDIR)/$(ARMPREFIX)-as
|
||||||
|
LD = $(ARMDIR)/$(ARMPREFIX)-ld
|
||||||
|
OBJDUMP = $(ARMDIR)/$(ARMPREFIX)-objdump
|
||||||
|
OBJCOPY = $(ARMDIR)/$(ARMPREFIX)-objcopy
|
||||||
|
|
||||||
|
DEFS = -D__COMROGUE_INTERNALS__
|
||||||
|
INCLUDES = -I../include -I../idl
|
||||||
|
CFLAGS = $(INCLUDES) -mabi=aapcs -mfloat-abi=hard -mcpu=arm1176jzf-s -Wall -O2 \
|
||||||
|
-nostdlib -nostartfiles -ffreestanding $(DEFS)
|
||||||
|
AFLAGS = -mcpu=arm1176jzf-s -mfloat-abi=hard
|
||||||
|
ASM_CPP_FLAGS = $(INCLUDES) $(DEFS) -D__ASM__
|
||||||
|
|
||||||
|
PRESTART_OBJS = prestart.o early_trace.o collect_startup.o early_mm.o
|
||||||
|
LIB_OBJS = divide.o qdivrem.o intlib.o str.o strcopymem.o
|
||||||
|
RES_OBJS = lowlevel.o trace.o
|
||||||
|
INIT_OBJS = start.o kistart.o
|
||||||
|
|
||||||
|
all: kernel.img
|
||||||
|
|
||||||
|
comrogue-kernel.elf : $(PRESTART_OBJS) $(LIB_OBJS) $(RES_OBJS) $(INIT_OBJS) comrogue-kernel.lds
|
||||||
|
$(CPP) $(ASM_CPP_FLAGS) -P -o comrogue-kernel.lds.parsed comrogue-kernel.lds
|
||||||
|
$(LD) -T comrogue-kernel.lds.parsed $(PRESTART_OBJS) $(LIB_OBJS) $(RES_OBJS) \
|
||||||
|
$(INIT_OBJS) -o comrogue-kernel.elf
|
||||||
|
|
||||||
|
kernel.img : comrogue-kernel.elf
|
||||||
|
$(OBJDUMP) -D comrogue-kernel.elf > comrogue-kernel.list
|
||||||
|
$(OBJDUMP) -t comrogue-kernel.elf > comrogue-kernel.syms
|
||||||
|
sort comrogue-kernel.syms > comrogue-kernel.syms.sorted
|
||||||
|
$(OBJCOPY) comrogue-kernel.elf -O binary kernel.img
|
||||||
|
|
||||||
|
%.o: %.S
|
||||||
|
$(CPP) $(ASM_CPP_FLAGS) -o $(basename $<).s $<
|
||||||
|
$(AS) $(AFLAGS) -o $@ $(basename $<).s
|
||||||
|
|
||||||
|
%.o: %.c
|
||||||
|
$(CC) $(CFLAGS) -c -o $@ $<
|
||||||
|
|
||||||
|
clean:
|
||||||
|
-rm *.o *.s kernel.img comrogue-kernel.elf comrogue-kernel.lds.parsed comrogue-kernel.list \
|
||||||
|
comrogue-kernel.syms*
|
245
kernel/collect_startup.c
Normal file
245
kernel/collect_startup.c
Normal file
|
@ -0,0 +1,245 @@
|
||||||
|
/*
|
||||||
|
* This file is part of the COMROGUE Operating System for Raspberry Pi
|
||||||
|
*
|
||||||
|
* Copyright (c) 2013, Eric J. Bowersox / Erbosoft Enterprises
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This program is free for commercial and non-commercial use as long as the following conditions are
|
||||||
|
* adhered to.
|
||||||
|
*
|
||||||
|
* Copyright in this file remains Eric J. Bowersox and/or Erbosoft, and as such any copyright notices
|
||||||
|
* in the code are not to be removed.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification, are permitted
|
||||||
|
* provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* * Redistributions of source code must retain the above copyright notice, this list of conditions and
|
||||||
|
* the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
|
||||||
|
* the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
|
||||||
|
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||||
|
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||||
|
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* "Raspberry Pi" is a trademark of the Raspberry Pi Foundation.
|
||||||
|
*/
|
||||||
|
#define __COMROGUE_PRESTART__
|
||||||
|
#include <comrogue/types.h>
|
||||||
|
#include <comrogue/internals/seg.h>
|
||||||
|
#include <comrogue/internals/mmu.h>
|
||||||
|
#include <comrogue/internals/startup.h>
|
||||||
|
|
||||||
|
/* The startup information buffer. */
|
||||||
|
SEG_INIT_DATA static STARTUP_INFO startup_info = {
|
||||||
|
.cb = sizeof(STARTUP_INFO),
|
||||||
|
.paTTB = 0,
|
||||||
|
.kaTTB = 0,
|
||||||
|
.cpgTTBGap = 0,
|
||||||
|
.paMPDB = 0,
|
||||||
|
.kaMPDB = 0,
|
||||||
|
.cpgMPDB = 0,
|
||||||
|
.paFirstPageTable = 0,
|
||||||
|
.cpgPageTables = 0,
|
||||||
|
.ctblFreeOnLastPage = 0,
|
||||||
|
.paFirstFree = 0,
|
||||||
|
.vmaFirstFree = 0
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Find a variable by name on the command line.
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* - pszCmdLine = Command-line pointer.
|
||||||
|
* - pszVariableName = Name of variable to search for.
|
||||||
|
*
|
||||||
|
* Returns:
|
||||||
|
* NULL if the variable was not found, otherwise a pointer to the first character in the command line
|
||||||
|
* following the variable name and associated = sign (first character of the value).
|
||||||
|
*/
|
||||||
|
SEG_INIT_CODE static PCSTR find_variable(PCSTR pszCmdLine, PCSTR pszVariableName)
|
||||||
|
{
|
||||||
|
register PCSTR p = pszCmdLine;
|
||||||
|
register PCSTR p1, q;
|
||||||
|
while (*p)
|
||||||
|
{
|
||||||
|
for (; *p && (*p != *pszVariableName); p++) ;
|
||||||
|
if (*p)
|
||||||
|
{
|
||||||
|
for (p1 = p, q = pszVariableName; *p1 && *q && (*p1 == *q); p1++, q++) ;
|
||||||
|
if (!(*q) && *p1 == '=')
|
||||||
|
return p1 + 1;
|
||||||
|
p++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Returns whether a character is a valid digit.
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* - ch = The character to be tested.
|
||||||
|
* - base = The base of the number being converted.
|
||||||
|
*
|
||||||
|
* Returns:
|
||||||
|
* TRUE if the character is a valid digit, FALSE otherwise.
|
||||||
|
*/
|
||||||
|
SEG_INIT_CODE static BOOL is_valid_digit(CHAR ch, UINT32 base)
|
||||||
|
{
|
||||||
|
register UINT32 nbase;
|
||||||
|
|
||||||
|
if (base > 10)
|
||||||
|
{
|
||||||
|
if ((ch >= 'a') && (ch < ('a' + base - 10)))
|
||||||
|
return TRUE;
|
||||||
|
if ((ch >= 'A') && (ch < ('A' + base - 10)))
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
nbase = (base > 10) ? 10 : base;
|
||||||
|
if ((ch >= '0') && (ch < ('0' + nbase)))
|
||||||
|
return TRUE;
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Decodes a number in a command-line parameter. Decoding stops at the first character that is not a valid digit.
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* - pVal = Pointer to the value in the command line.
|
||||||
|
* - base = Base of the number to convert. If this is 16, the decoder will skip over a "0x" or "0X" prefix
|
||||||
|
* of the value, if one exists.
|
||||||
|
*
|
||||||
|
* Returns:
|
||||||
|
* The converted numeric value.
|
||||||
|
*/
|
||||||
|
SEG_INIT_CODE static UINT32 decode_number(PCSTR pVal, UINT32 base)
|
||||||
|
{
|
||||||
|
register UINT32 accum = 0;
|
||||||
|
register UINT32 digit;
|
||||||
|
|
||||||
|
if ((base == 16) && (*pVal == '0') && ((*(pVal + 1) == 'x') || (*(pVal + 1) == 'X')))
|
||||||
|
pVal += 2;
|
||||||
|
while (is_valid_digit(*pVal, base))
|
||||||
|
{
|
||||||
|
if (*pVal >= 'a')
|
||||||
|
digit = (*pVal - 'a') + 10;
|
||||||
|
else if (*pVal >= 'A')
|
||||||
|
digit = (*pVal - 'A') + 10;
|
||||||
|
else
|
||||||
|
digit = (*pVal - '0');
|
||||||
|
accum = accum * base + digit;
|
||||||
|
pVal++;
|
||||||
|
}
|
||||||
|
return accum;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Parses the command line passed in via the ATAGS and extracts certain values to the startup info
|
||||||
|
* data structure.
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* - pszCmdLine = Pointer to the command line.
|
||||||
|
*
|
||||||
|
* Returns:
|
||||||
|
* Nothing.
|
||||||
|
*
|
||||||
|
* Side effects:
|
||||||
|
* Modifies the "startup_info" structure.
|
||||||
|
*/
|
||||||
|
SEG_INIT_CODE static void parse_cmdline(PCSTR pszCmdLine)
|
||||||
|
{
|
||||||
|
static DECLARE_INIT_STRING8_CONST(szFBWidth, "bcm2708_fb.fbwidth");
|
||||||
|
static DECLARE_INIT_STRING8_CONST(szFBHeight, "bcm2708_fb.fbheight");
|
||||||
|
static DECLARE_INIT_STRING8_CONST(szRevision, "bcm2708.boardrev");
|
||||||
|
static DECLARE_INIT_STRING8_CONST(szSerial, "bcm2708.serial");
|
||||||
|
static DECLARE_INIT_STRING8_CONST(szMACAddr, "smsc95xx.macaddr");
|
||||||
|
static DECLARE_INIT_STRING8_CONST(szEMMCFreq, "sdhci-bcm2708.emmc_clock_freq");
|
||||||
|
static DECLARE_INIT_STRING8_CONST(szVCMemBase, "vc_mem.mem_base");
|
||||||
|
static DECLARE_INIT_STRING8_CONST(szVCMemSize, "vc_mem.mem_size");
|
||||||
|
register PCSTR p;
|
||||||
|
register int i;
|
||||||
|
|
||||||
|
p = find_variable(pszCmdLine, szFBWidth);
|
||||||
|
startup_info.cxFBWidth = (UINT16)(p ? decode_number(p, 10) : 0);
|
||||||
|
p = find_variable(pszCmdLine, szFBHeight);
|
||||||
|
startup_info.cyFBHeight = (UINT16)(p ? decode_number(p, 10) : 0);
|
||||||
|
p = find_variable(pszCmdLine, szRevision);
|
||||||
|
startup_info.uiRevision = (p ? decode_number(p, 16) : 0);
|
||||||
|
p = find_variable(pszCmdLine, szSerial);
|
||||||
|
startup_info.uiSerialNumber = (p ? decode_number(p, 16) : 0);
|
||||||
|
p = find_variable(pszCmdLine, szMACAddr);
|
||||||
|
if (p)
|
||||||
|
{
|
||||||
|
for (i=0; i<6; i++)
|
||||||
|
{
|
||||||
|
startup_info.abMACAddress[i] = (BYTE)decode_number(p, 16);
|
||||||
|
p += 3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (i=0; i<6; i++)
|
||||||
|
startup_info.abMACAddress[i] = 0;
|
||||||
|
}
|
||||||
|
p = find_variable(pszCmdLine, szEMMCFreq);
|
||||||
|
startup_info.uiEMMCClockFreq = (p ? decode_number(p, 10) : 0);
|
||||||
|
p = find_variable(pszCmdLine, szVCMemBase);
|
||||||
|
startup_info.paVCMem = (PHYSADDR)(p ? decode_number(p, 16) : 0);
|
||||||
|
p = find_variable(pszCmdLine, szVCMemSize);
|
||||||
|
startup_info.cbVCMem = (p ? decode_number(p, 16) : 0);
|
||||||
|
startup_info.cpgSystemTotal = startup_info.cbVCMem >> SYS_PAGE_BITS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Collects startup information in an init-data buffer and returns a pointer to that buffer.
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* - always0 = Always 0.
|
||||||
|
* - uiMachineType = Machine type constant.
|
||||||
|
* - pAtags = Pointer to ATAGS data set up before kernel was started.
|
||||||
|
*
|
||||||
|
* Returns:
|
||||||
|
* A pointer to the assembled STARTUP_INFO data structure.
|
||||||
|
*
|
||||||
|
* Side effects:
|
||||||
|
* Modifies the "startup_info" structure, which it returns a pointer to.
|
||||||
|
*/
|
||||||
|
SEG_INIT_CODE PSTARTUP_INFO KiCollectStartupInfo(UINT32 always0, UINT32 uiMachineType, PATAG_HEADER pAtags)
|
||||||
|
{
|
||||||
|
/* Fill in the information we can calculate right away. */
|
||||||
|
startup_info.uiMachineType = uiMachineType;
|
||||||
|
|
||||||
|
/* Scan the ATAG headers to determine what other info to include. */
|
||||||
|
while (pAtags->uiTag != ATAGTYPE_NONE)
|
||||||
|
{
|
||||||
|
switch (pAtags->uiTag)
|
||||||
|
{
|
||||||
|
case ATAGTYPE_CORE:
|
||||||
|
/* nothing really useful in this block */
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ATAGTYPE_MEM:
|
||||||
|
/* fill in total number of available system memory pages */
|
||||||
|
startup_info.cpgSystemAvail = ((PATAG_MEM)pAtags)->uiSize >> SYS_PAGE_BITS;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ATAGTYPE_CMDLINE:
|
||||||
|
parse_cmdline(((PATAG_CMDLINE)pAtags)->szCommandLine);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
/* no other ATAG types are seen on Raspberry Pi */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
pAtags = kiNextATAG(pAtags);
|
||||||
|
}
|
||||||
|
|
||||||
|
return &startup_info;
|
||||||
|
}
|
134
kernel/comrogue-kernel.lds
Normal file
134
kernel/comrogue-kernel.lds
Normal file
|
@ -0,0 +1,134 @@
|
||||||
|
/*
|
||||||
|
* This file is part of the COMROGUE Operating System for Raspberry Pi
|
||||||
|
*
|
||||||
|
* Copyright (c) 2013, Eric J. Bowersox / Erbosoft Enterprises
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This program is free for commercial and non-commercial use as long as the following conditions are
|
||||||
|
* adhered to.
|
||||||
|
*
|
||||||
|
* Copyright in this file remains Eric J. Bowersox and/or Erbosoft, and as such any copyright notices
|
||||||
|
* in the code are not to be removed.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification, are permitted
|
||||||
|
* provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* * Redistributions of source code must retain the above copyright notice, this list of conditions and
|
||||||
|
* the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
|
||||||
|
* the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
|
||||||
|
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||||
|
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||||
|
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* "Raspberry Pi" is a trademark of the Raspberry Pi Foundation.
|
||||||
|
*/
|
||||||
|
#include <comrogue/internals/mmu.h>
|
||||||
|
#include <comrogue/internals/layout.h>
|
||||||
|
|
||||||
|
ENTRY(COMROGUEPrestart)
|
||||||
|
|
||||||
|
SECTIONS
|
||||||
|
{
|
||||||
|
/* all these are prestart code that runs in low memory with MMU off */
|
||||||
|
/* space is reclaimed once the kernel begins operation in high memory with MMU on */
|
||||||
|
.prestart.text PHYSADDR_LOAD : AT (PHYSADDR_LOAD) {
|
||||||
|
paPrestartCode = .;
|
||||||
|
*(.prestartHEAD.text) /* must be first! */
|
||||||
|
*(.prestart.text)
|
||||||
|
*(.prestart.rodata)
|
||||||
|
*(.prestart.rodata.*)
|
||||||
|
. = ALIGN(SYS_PAGE_SIZE);
|
||||||
|
}
|
||||||
|
cpgPrestartCode = (. - paPrestartCode) >> SYS_PAGE_BITS;
|
||||||
|
paPrestartData = .;
|
||||||
|
|
||||||
|
.prestart.data : AT(paPrestartData) {
|
||||||
|
*(.prestart.data)
|
||||||
|
. = ALIGN(SYS_PAGE_SIZE);
|
||||||
|
}
|
||||||
|
cpgPrestartData = (. - paPrestartData) >> SYS_PAGE_BITS;
|
||||||
|
cpgPrestartTotal = . >> SYS_PAGE_BITS;
|
||||||
|
paLibraryCode = .;
|
||||||
|
|
||||||
|
/* kernel library code, in high memory mapped to be visible to user processes */
|
||||||
|
.lib.text VMADDR_LIBRARY_FENCE : AT (paLibraryCode) {
|
||||||
|
vmaLibraryCode = .;
|
||||||
|
*(.lib.text)
|
||||||
|
*(.lib.rodata)
|
||||||
|
*(.lib.rodata.*)
|
||||||
|
. = ALIGN(SYS_PAGE_SIZE);
|
||||||
|
}
|
||||||
|
cpgLibraryCode = (. - vmaLibraryCode) >> SYS_PAGE_BITS;
|
||||||
|
paKernelCode = paLibraryCode + (. - vmaLibraryCode);
|
||||||
|
|
||||||
|
/* kernel resident code, runs in high memory with MMU on */
|
||||||
|
.text VMADDR_KERNEL_FENCE : AT(paKernelCode) {
|
||||||
|
vmaKernelCode = .;
|
||||||
|
*(.text)
|
||||||
|
*(.rodata)
|
||||||
|
*(.rodata.*)
|
||||||
|
. = ALIGN(SYS_PAGE_SIZE);
|
||||||
|
}
|
||||||
|
cpgKernelCode = (. - vmaKernelCode) >> SYS_PAGE_BITS;
|
||||||
|
paKernelData = paKernelCode + (. - vmaKernelCode);
|
||||||
|
|
||||||
|
.data : AT(paKernelData) {
|
||||||
|
vmaKernelData = .;
|
||||||
|
*(.data)
|
||||||
|
. = ALIGN(SYS_PAGE_SIZE);
|
||||||
|
}
|
||||||
|
cpgKernelData = (. - vmaKernelData) >> SYS_PAGE_BITS;
|
||||||
|
paKernelBss = paKernelData + (. - vmaKernelData);
|
||||||
|
|
||||||
|
.bss : AT(paKernelBss) {
|
||||||
|
vmaKernelBss = .;
|
||||||
|
*(.bss)
|
||||||
|
*(COMMON)
|
||||||
|
. = ALIGN(SYS_PAGE_SIZE);
|
||||||
|
}
|
||||||
|
cpgKernelBss = (. - vmaKernelBss) >> SYS_PAGE_BITS;
|
||||||
|
paInitCode = paKernelBss + (. - vmaKernelBss);
|
||||||
|
|
||||||
|
/* kernel one-time initialization code, runs in high memory with MMU on */
|
||||||
|
/* space is reclaimed once the kernel finishes initialization */
|
||||||
|
.init.text : AT(paInitCode) {
|
||||||
|
vmaInitCode = .;
|
||||||
|
*(.initHEAD.text) /* must be first! */
|
||||||
|
*(.init.text)
|
||||||
|
*(.init.rodata)
|
||||||
|
*(.init.rodata.*)
|
||||||
|
. = ALIGN(SYS_PAGE_SIZE);
|
||||||
|
}
|
||||||
|
cpgInitCode = (. - vmaInitCode) >> SYS_PAGE_BITS;
|
||||||
|
paInitData = paInitCode + (. - vmaInitCode);
|
||||||
|
|
||||||
|
.init.data : AT(paInitData) {
|
||||||
|
vmaInitData = .;
|
||||||
|
*(.init.data)
|
||||||
|
. = ALIGN(SYS_PAGE_SIZE);
|
||||||
|
}
|
||||||
|
cpgInitData = (. - vmaInitData) >> SYS_PAGE_BITS;
|
||||||
|
paInitBss = paInitData + (. - vmaInitData);
|
||||||
|
|
||||||
|
.init.bss : AT(paInitBss) {
|
||||||
|
vmaInitBss = .;
|
||||||
|
*(.init.bss)
|
||||||
|
. = ALIGN(SYS_PAGE_SIZE);
|
||||||
|
}
|
||||||
|
cpgInitBss = (. - vmaInitBss) >> SYS_PAGE_BITS;
|
||||||
|
paFirstFree = paInitBss + (. - vmaInitBss);
|
||||||
|
vmaFirstFree = .;
|
||||||
|
|
||||||
|
/DISCARD/ : {
|
||||||
|
*(.comment)
|
||||||
|
*(.note*)
|
||||||
|
*(.ARM.attributes)
|
||||||
|
}
|
||||||
|
}
|
479
kernel/divide.S
Normal file
479
kernel/divide.S
Normal file
|
@ -0,0 +1,479 @@
|
||||||
|
/*
|
||||||
|
* Portions of this file are subject to the following notices:
|
||||||
|
*
|
||||||
|
* Copyright (C) 2012 Andrew Turner
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2012 The NetBSD Foundation, Inc.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This code is derived from software contributed to The NetBSD Foundation
|
||||||
|
* by Matt Thomas of 3am Software Foundry.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
/* Derived from FreeBSD libkern divsi3.S, uldivmod.S, and ldivmod.S, munged by Erbo to COMROGUE standards */
|
||||||
|
.section ".lib.text"
|
||||||
|
|
||||||
|
.globl __aeabi_uidiv
|
||||||
|
.globl __aeabi_uidivmod
|
||||||
|
__aeabi_uidiv:
|
||||||
|
__aeabi_uidivmod:
|
||||||
|
eor r0, r1, r0 /* r0 = r0 / r1; r1 = r0 % r1 */
|
||||||
|
eor r1, r0, r1
|
||||||
|
eor r0, r1, r0 /* r0 = r1 / r0; r1 = r1 % r0 */
|
||||||
|
|
||||||
|
cmp r0, #1
|
||||||
|
bcc .L_overflow
|
||||||
|
beq .L_divide_l0
|
||||||
|
mov ip, #0
|
||||||
|
movs r1, r1
|
||||||
|
bpl .L_divide_l1
|
||||||
|
orr ip, ip, #0x20000000 /* indicates r1 is negative */
|
||||||
|
movs r1, r1, lsr #1
|
||||||
|
orrcs ip, ip, #0x10000000 /* indicates bit 0 of r1 */
|
||||||
|
b .L_divide_l1
|
||||||
|
|
||||||
|
.L_divide_l0:
|
||||||
|
mov r0, r1 /* r0 == 1 */
|
||||||
|
mov r1, #0
|
||||||
|
bx lr
|
||||||
|
|
||||||
|
.globl __aeabi_idiv
|
||||||
|
.globl __aeabi_idivmod
|
||||||
|
__aeabi_idiv:
|
||||||
|
__aeabi_idivmod:
|
||||||
|
eor r0, r1, r0 /* r0 = r0 / r1; r1 = r0 % r1 */
|
||||||
|
eor r1, r0, r1
|
||||||
|
eor r0, r1, r0 /* r0 = r1 / r0; r1 = r1 % r0 */
|
||||||
|
|
||||||
|
cmp r0, #1
|
||||||
|
bcc .L_overflow
|
||||||
|
beq .L_divide_l0
|
||||||
|
ands ip, r0, #0x80000000
|
||||||
|
rsbmi r0, r0, #0
|
||||||
|
ands r2, r1, #0x80000000
|
||||||
|
eor ip, ip, r2
|
||||||
|
rsbmi r1, r1, #0
|
||||||
|
orr ip, r2, ip, lsr #1 /* bit 0x40000000 = negative division, bit 0x80000000 = negative remainder */
|
||||||
|
|
||||||
|
.L_divide_l1:
|
||||||
|
mov r2, #1
|
||||||
|
mov r3, #0
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If the highest bit of the dividend is set, we have to be
|
||||||
|
* careful when shifting the divisor. Test this.
|
||||||
|
*/
|
||||||
|
movs r1, r1
|
||||||
|
bpl .L_old_code
|
||||||
|
|
||||||
|
/*
|
||||||
|
* At this point, the highest bit of r1 is known to be set.
|
||||||
|
* We abuse this below in the tst instructions.
|
||||||
|
*/
|
||||||
|
tst r1, r0 /*, lsl #0 */
|
||||||
|
bmi .L_divide_b1
|
||||||
|
tst r1, r0, lsl #1
|
||||||
|
bmi .L_divide_b2
|
||||||
|
tst r1, r0, lsl #2
|
||||||
|
bmi .L_divide_b3
|
||||||
|
tst r1, r0, lsl #3
|
||||||
|
bmi .L_divide_b4
|
||||||
|
tst r1, r0, lsl #4
|
||||||
|
bmi .L_divide_b5
|
||||||
|
tst r1, r0, lsl #5
|
||||||
|
bmi .L_divide_b6
|
||||||
|
tst r1, r0, lsl #6
|
||||||
|
bmi .L_divide_b7
|
||||||
|
tst r1, r0, lsl #7
|
||||||
|
bmi .L_divide_b8
|
||||||
|
tst r1, r0, lsl #8
|
||||||
|
bmi .L_divide_b9
|
||||||
|
tst r1, r0, lsl #9
|
||||||
|
bmi .L_divide_b10
|
||||||
|
tst r1, r0, lsl #10
|
||||||
|
bmi .L_divide_b11
|
||||||
|
tst r1, r0, lsl #11
|
||||||
|
bmi .L_divide_b12
|
||||||
|
tst r1, r0, lsl #12
|
||||||
|
bmi .L_divide_b13
|
||||||
|
tst r1, r0, lsl #13
|
||||||
|
bmi .L_divide_b14
|
||||||
|
tst r1, r0, lsl #14
|
||||||
|
bmi .L_divide_b15
|
||||||
|
tst r1, r0, lsl #15
|
||||||
|
bmi .L_divide_b16
|
||||||
|
tst r1, r0, lsl #16
|
||||||
|
bmi .L_divide_b17
|
||||||
|
tst r1, r0, lsl #17
|
||||||
|
bmi .L_divide_b18
|
||||||
|
tst r1, r0, lsl #18
|
||||||
|
bmi .L_divide_b19
|
||||||
|
tst r1, r0, lsl #19
|
||||||
|
bmi .L_divide_b20
|
||||||
|
tst r1, r0, lsl #20
|
||||||
|
bmi .L_divide_b21
|
||||||
|
tst r1, r0, lsl #21
|
||||||
|
bmi .L_divide_b22
|
||||||
|
tst r1, r0, lsl #22
|
||||||
|
bmi .L_divide_b23
|
||||||
|
tst r1, r0, lsl #23
|
||||||
|
bmi .L_divide_b24
|
||||||
|
tst r1, r0, lsl #24
|
||||||
|
bmi .L_divide_b25
|
||||||
|
tst r1, r0, lsl #25
|
||||||
|
bmi .L_divide_b26
|
||||||
|
tst r1, r0, lsl #26
|
||||||
|
bmi .L_divide_b27
|
||||||
|
tst r1, r0, lsl #27
|
||||||
|
bmi .L_divide_b28
|
||||||
|
tst r1, r0, lsl #28
|
||||||
|
bmi .L_divide_b29
|
||||||
|
tst r1, r0, lsl #29
|
||||||
|
bmi .L_divide_b30
|
||||||
|
tst r1, r0, lsl #30
|
||||||
|
bmi .L_divide_b31
|
||||||
|
/*
|
||||||
|
* instead of:
|
||||||
|
* tst r1, r0, lsl #31
|
||||||
|
* bmi .L_divide_b32
|
||||||
|
*/
|
||||||
|
b .L_divide_b32
|
||||||
|
|
||||||
|
.L_old_code:
|
||||||
|
cmp r1, r0
|
||||||
|
bcc .L_divide_b0
|
||||||
|
cmp r1, r0, lsl #1
|
||||||
|
bcc .L_divide_b1
|
||||||
|
cmp r1, r0, lsl #2
|
||||||
|
bcc .L_divide_b2
|
||||||
|
cmp r1, r0, lsl #3
|
||||||
|
bcc .L_divide_b3
|
||||||
|
cmp r1, r0, lsl #4
|
||||||
|
bcc .L_divide_b4
|
||||||
|
cmp r1, r0, lsl #5
|
||||||
|
bcc .L_divide_b5
|
||||||
|
cmp r1, r0, lsl #6
|
||||||
|
bcc .L_divide_b6
|
||||||
|
cmp r1, r0, lsl #7
|
||||||
|
bcc .L_divide_b7
|
||||||
|
cmp r1, r0, lsl #8
|
||||||
|
bcc .L_divide_b8
|
||||||
|
cmp r1, r0, lsl #9
|
||||||
|
bcc .L_divide_b9
|
||||||
|
cmp r1, r0, lsl #10
|
||||||
|
bcc .L_divide_b10
|
||||||
|
cmp r1, r0, lsl #11
|
||||||
|
bcc .L_divide_b11
|
||||||
|
cmp r1, r0, lsl #12
|
||||||
|
bcc .L_divide_b12
|
||||||
|
cmp r1, r0, lsl #13
|
||||||
|
bcc .L_divide_b13
|
||||||
|
cmp r1, r0, lsl #14
|
||||||
|
bcc .L_divide_b14
|
||||||
|
cmp r1, r0, lsl #15
|
||||||
|
bcc .L_divide_b15
|
||||||
|
cmp r1, r0, lsl #16
|
||||||
|
bcc .L_divide_b16
|
||||||
|
cmp r1, r0, lsl #17
|
||||||
|
bcc .L_divide_b17
|
||||||
|
cmp r1, r0, lsl #18
|
||||||
|
bcc .L_divide_b18
|
||||||
|
cmp r1, r0, lsl #19
|
||||||
|
bcc .L_divide_b19
|
||||||
|
cmp r1, r0, lsl #20
|
||||||
|
bcc .L_divide_b20
|
||||||
|
cmp r1, r0, lsl #21
|
||||||
|
bcc .L_divide_b21
|
||||||
|
cmp r1, r0, lsl #22
|
||||||
|
bcc .L_divide_b22
|
||||||
|
cmp r1, r0, lsl #23
|
||||||
|
bcc .L_divide_b23
|
||||||
|
cmp r1, r0, lsl #24
|
||||||
|
bcc .L_divide_b24
|
||||||
|
cmp r1, r0, lsl #25
|
||||||
|
bcc .L_divide_b25
|
||||||
|
cmp r1, r0, lsl #26
|
||||||
|
bcc .L_divide_b26
|
||||||
|
cmp r1, r0, lsl #27
|
||||||
|
bcc .L_divide_b27
|
||||||
|
cmp r1, r0, lsl #28
|
||||||
|
bcc .L_divide_b28
|
||||||
|
cmp r1, r0, lsl #29
|
||||||
|
bcc .L_divide_b29
|
||||||
|
cmp r1, r0, lsl #30
|
||||||
|
bcc .L_divide_b30
|
||||||
|
.L_divide_b32:
|
||||||
|
cmp r1, r0, lsl #31
|
||||||
|
subhs r1, r1,r0, lsl #31
|
||||||
|
addhs r3, r3,r2, lsl #31
|
||||||
|
.L_divide_b31:
|
||||||
|
cmp r1, r0, lsl #30
|
||||||
|
subhs r1, r1,r0, lsl #30
|
||||||
|
addhs r3, r3,r2, lsl #30
|
||||||
|
.L_divide_b30:
|
||||||
|
cmp r1, r0, lsl #29
|
||||||
|
subhs r1, r1,r0, lsl #29
|
||||||
|
addhs r3, r3,r2, lsl #29
|
||||||
|
.L_divide_b29:
|
||||||
|
cmp r1, r0, lsl #28
|
||||||
|
subhs r1, r1,r0, lsl #28
|
||||||
|
addhs r3, r3,r2, lsl #28
|
||||||
|
.L_divide_b28:
|
||||||
|
cmp r1, r0, lsl #27
|
||||||
|
subhs r1, r1,r0, lsl #27
|
||||||
|
addhs r3, r3,r2, lsl #27
|
||||||
|
.L_divide_b27:
|
||||||
|
cmp r1, r0, lsl #26
|
||||||
|
subhs r1, r1,r0, lsl #26
|
||||||
|
addhs r3, r3,r2, lsl #26
|
||||||
|
.L_divide_b26:
|
||||||
|
cmp r1, r0, lsl #25
|
||||||
|
subhs r1, r1,r0, lsl #25
|
||||||
|
addhs r3, r3,r2, lsl #25
|
||||||
|
.L_divide_b25:
|
||||||
|
cmp r1, r0, lsl #24
|
||||||
|
subhs r1, r1,r0, lsl #24
|
||||||
|
addhs r3, r3,r2, lsl #24
|
||||||
|
.L_divide_b24:
|
||||||
|
cmp r1, r0, lsl #23
|
||||||
|
subhs r1, r1,r0, lsl #23
|
||||||
|
addhs r3, r3,r2, lsl #23
|
||||||
|
.L_divide_b23:
|
||||||
|
cmp r1, r0, lsl #22
|
||||||
|
subhs r1, r1,r0, lsl #22
|
||||||
|
addhs r3, r3,r2, lsl #22
|
||||||
|
.L_divide_b22:
|
||||||
|
cmp r1, r0, lsl #21
|
||||||
|
subhs r1, r1,r0, lsl #21
|
||||||
|
addhs r3, r3,r2, lsl #21
|
||||||
|
.L_divide_b21:
|
||||||
|
cmp r1, r0, lsl #20
|
||||||
|
subhs r1, r1,r0, lsl #20
|
||||||
|
addhs r3, r3,r2, lsl #20
|
||||||
|
.L_divide_b20:
|
||||||
|
cmp r1, r0, lsl #19
|
||||||
|
subhs r1, r1,r0, lsl #19
|
||||||
|
addhs r3, r3,r2, lsl #19
|
||||||
|
.L_divide_b19:
|
||||||
|
cmp r1, r0, lsl #18
|
||||||
|
subhs r1, r1,r0, lsl #18
|
||||||
|
addhs r3, r3,r2, lsl #18
|
||||||
|
.L_divide_b18:
|
||||||
|
cmp r1, r0, lsl #17
|
||||||
|
subhs r1, r1,r0, lsl #17
|
||||||
|
addhs r3, r3,r2, lsl #17
|
||||||
|
.L_divide_b17:
|
||||||
|
cmp r1, r0, lsl #16
|
||||||
|
subhs r1, r1,r0, lsl #16
|
||||||
|
addhs r3, r3,r2, lsl #16
|
||||||
|
.L_divide_b16:
|
||||||
|
cmp r1, r0, lsl #15
|
||||||
|
subhs r1, r1,r0, lsl #15
|
||||||
|
addhs r3, r3,r2, lsl #15
|
||||||
|
.L_divide_b15:
|
||||||
|
cmp r1, r0, lsl #14
|
||||||
|
subhs r1, r1,r0, lsl #14
|
||||||
|
addhs r3, r3,r2, lsl #14
|
||||||
|
.L_divide_b14:
|
||||||
|
cmp r1, r0, lsl #13
|
||||||
|
subhs r1, r1,r0, lsl #13
|
||||||
|
addhs r3, r3,r2, lsl #13
|
||||||
|
.L_divide_b13:
|
||||||
|
cmp r1, r0, lsl #12
|
||||||
|
subhs r1, r1,r0, lsl #12
|
||||||
|
addhs r3, r3,r2, lsl #12
|
||||||
|
.L_divide_b12:
|
||||||
|
cmp r1, r0, lsl #11
|
||||||
|
subhs r1, r1,r0, lsl #11
|
||||||
|
addhs r3, r3,r2, lsl #11
|
||||||
|
.L_divide_b11:
|
||||||
|
cmp r1, r0, lsl #10
|
||||||
|
subhs r1, r1,r0, lsl #10
|
||||||
|
addhs r3, r3,r2, lsl #10
|
||||||
|
.L_divide_b10:
|
||||||
|
cmp r1, r0, lsl #9
|
||||||
|
subhs r1, r1,r0, lsl #9
|
||||||
|
addhs r3, r3,r2, lsl #9
|
||||||
|
.L_divide_b9:
|
||||||
|
cmp r1, r0, lsl #8
|
||||||
|
subhs r1, r1,r0, lsl #8
|
||||||
|
addhs r3, r3,r2, lsl #8
|
||||||
|
.L_divide_b8:
|
||||||
|
cmp r1, r0, lsl #7
|
||||||
|
subhs r1, r1,r0, lsl #7
|
||||||
|
addhs r3, r3,r2, lsl #7
|
||||||
|
.L_divide_b7:
|
||||||
|
cmp r1, r0, lsl #6
|
||||||
|
subhs r1, r1,r0, lsl #6
|
||||||
|
addhs r3, r3,r2, lsl #6
|
||||||
|
.L_divide_b6:
|
||||||
|
cmp r1, r0, lsl #5
|
||||||
|
subhs r1, r1,r0, lsl #5
|
||||||
|
addhs r3, r3,r2, lsl #5
|
||||||
|
.L_divide_b5:
|
||||||
|
cmp r1, r0, lsl #4
|
||||||
|
subhs r1, r1,r0, lsl #4
|
||||||
|
addhs r3, r3,r2, lsl #4
|
||||||
|
.L_divide_b4:
|
||||||
|
cmp r1, r0, lsl #3
|
||||||
|
subhs r1, r1,r0, lsl #3
|
||||||
|
addhs r3, r3,r2, lsl #3
|
||||||
|
.L_divide_b3:
|
||||||
|
cmp r1, r0, lsl #2
|
||||||
|
subhs r1, r1,r0, lsl #2
|
||||||
|
addhs r3, r3,r2, lsl #2
|
||||||
|
.L_divide_b2:
|
||||||
|
cmp r1, r0, lsl #1
|
||||||
|
subhs r1, r1,r0, lsl #1
|
||||||
|
addhs r3, r3,r2, lsl #1
|
||||||
|
.L_divide_b1:
|
||||||
|
cmp r1, r0
|
||||||
|
subhs r1, r1, r0
|
||||||
|
addhs r3, r3, r2
|
||||||
|
.L_divide_b0:
|
||||||
|
|
||||||
|
tst ip, #0x20000000
|
||||||
|
bne .L_udivide_l1
|
||||||
|
mov r0, r3
|
||||||
|
cmp ip, #0
|
||||||
|
rsbmi r1, r1, #0
|
||||||
|
movs ip, ip, lsl #1
|
||||||
|
bicmi r0, r0, #0x80000000 /* Fix incase we divided 0x80000000 */
|
||||||
|
rsbmi r0, r0, #0
|
||||||
|
bx lr
|
||||||
|
|
||||||
|
.L_udivide_l1:
|
||||||
|
tst ip, #0x10000000
|
||||||
|
mov r1, r1, lsl #1
|
||||||
|
orrne r1, r1, #1
|
||||||
|
mov r3, r3, lsl #1
|
||||||
|
cmp r1, r0
|
||||||
|
subhs r1, r1, r0
|
||||||
|
addhs r3, r3, r2
|
||||||
|
mov r0, r3
|
||||||
|
bx lr
|
||||||
|
|
||||||
|
.L_overflow:
|
||||||
|
/* TODO: cause an exception or something? */
|
||||||
|
mvn r0, #0
|
||||||
|
bx lr
|
||||||
|
|
||||||
|
.globl __aeabi_uldivmod
|
||||||
|
__aeabi_uldivmod:
|
||||||
|
push {r4,lr}
|
||||||
|
sub sp, sp, #8
|
||||||
|
mov r4, sp
|
||||||
|
push {r4}
|
||||||
|
bl __qdivrem
|
||||||
|
pop {r4}
|
||||||
|
/*
|
||||||
|
* The remainder is already on the stack just waiting to be popped
|
||||||
|
* into r2/r3.
|
||||||
|
*/
|
||||||
|
pop {r2-r4,lr}
|
||||||
|
bx lr
|
||||||
|
|
||||||
|
.globl __aeabi_ldivmod
|
||||||
|
__aeabi_ldivmod:
|
||||||
|
push {r4-r5, sl, lr}
|
||||||
|
mov r5, #0 /* r5 = negative indicator */
|
||||||
|
|
||||||
|
cmp r3, #0
|
||||||
|
bge 2f
|
||||||
|
eor r5, r5, #1 /* flip quotient sign */
|
||||||
|
bl .Lnegate_b
|
||||||
|
bcs .Lmaxdenom
|
||||||
|
|
||||||
|
2:
|
||||||
|
cmp r1, #0
|
||||||
|
/* bge 3f */
|
||||||
|
eorlt r5, r5, #3 /* flip quotient sign, flip remainder sign */
|
||||||
|
bllt .Lnegate_a
|
||||||
|
3:
|
||||||
|
/*
|
||||||
|
* Arguments are setup, allocate some stack for the remainder
|
||||||
|
* and call __qdivrem for the heavy lifting.
|
||||||
|
*/
|
||||||
|
sub sp, sp, #8
|
||||||
|
mov r4, sp /* pointer to remainder */
|
||||||
|
push {r4}
|
||||||
|
bl __qdivrem
|
||||||
|
pop {r4}
|
||||||
|
|
||||||
|
teq r5, #0 /* any signs to flip? */
|
||||||
|
/*
|
||||||
|
* The quotient is already in the right place and neither value
|
||||||
|
* needs its sign flipped.
|
||||||
|
*/
|
||||||
|
popeq {r2-r5, sl, lr}
|
||||||
|
bxeq lr
|
||||||
|
|
||||||
|
pop {r2, r3}
|
||||||
|
tst r5, #2 /* does remainder need to be negative? */
|
||||||
|
bleq .Lnegate_b
|
||||||
|
tst r5, #1 /* does quotient need to be negative? */
|
||||||
|
bleq .Lnegate_a
|
||||||
|
pop {r4-r5, sl, lr}
|
||||||
|
bx lr
|
||||||
|
|
||||||
|
.Lnegate_a:
|
||||||
|
rsbs r0, r0, #0
|
||||||
|
rsc r1, r1, #0
|
||||||
|
bx lr
|
||||||
|
|
||||||
|
.Lnegate_b:
|
||||||
|
rsbs r2, r2, #0
|
||||||
|
rsc r3, r3, #0
|
||||||
|
bx lr
|
||||||
|
|
||||||
|
.Lmaxdenom:
|
||||||
|
/*
|
||||||
|
* We had a carry so the denominator must have INT64_MIN
|
||||||
|
* Also BLO and BHI never changed values so we can use
|
||||||
|
* them to see if the numerator has the same value. We
|
||||||
|
* don't have to worry about sign.
|
||||||
|
*/
|
||||||
|
teq r3, r1
|
||||||
|
teqeq r2, r0
|
||||||
|
bne 1f
|
||||||
|
|
||||||
|
/*
|
||||||
|
* They were equal, so we return a quotient of 1 and remainder of 0.
|
||||||
|
*/
|
||||||
|
mov r0, #1
|
||||||
|
mov r1, #0
|
||||||
|
mov r2, #0
|
||||||
|
mov r3, #0
|
||||||
|
pop {r4-r5, sl, lr}
|
||||||
|
bx lr
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Our remainder must be the numerator and our quotient is 0.
|
||||||
|
*/
|
||||||
|
1: mov r2, r0
|
||||||
|
mov r3, r1
|
||||||
|
mov r0, #0
|
||||||
|
mov r1, #0
|
||||||
|
pop {r4-r5, sl, lr}
|
||||||
|
bx lr
|
398
kernel/early_mm.c
Normal file
398
kernel/early_mm.c
Normal file
|
@ -0,0 +1,398 @@
|
||||||
|
/*
|
||||||
|
* This file is part of the COMROGUE Operating System for Raspberry Pi
|
||||||
|
*
|
||||||
|
* Copyright (c) 2013, Eric J. Bowersox / Erbosoft Enterprises
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This program is free for commercial and non-commercial use as long as the following conditions are
|
||||||
|
* adhered to.
|
||||||
|
*
|
||||||
|
* Copyright in this file remains Eric J. Bowersox and/or Erbosoft, and as such any copyright notices
|
||||||
|
* in the code are not to be removed.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification, are permitted
|
||||||
|
* provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* * Redistributions of source code must retain the above copyright notice, this list of conditions and
|
||||||
|
* the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
|
||||||
|
* the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
|
||||||
|
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||||
|
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||||
|
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* "Raspberry Pi" is a trademark of the Raspberry Pi Foundation.
|
||||||
|
*/
|
||||||
|
#define __COMROGUE_PRESTART__
|
||||||
|
#include <comrogue/types.h>
|
||||||
|
#include <comrogue/internals/seg.h>
|
||||||
|
#include <comrogue/internals/layout.h>
|
||||||
|
#include <comrogue/internals/mmu.h>
|
||||||
|
#include <comrogue/internals/startup.h>
|
||||||
|
#include <comrogue/internals/trace.h>
|
||||||
|
|
||||||
|
#ifdef THIS_FILE
|
||||||
|
#undef THIS_FILE
|
||||||
|
DECLARE_THIS_FILE
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------
|
||||||
|
* Early memory-management code that handles creating the mappings for the TTB
|
||||||
|
*-----------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Data stored in here temporarily and reflected back to startup info when we're done. */
|
||||||
|
SEG_INIT_DATA static PTTB g_pTTB = NULL; /* pointer to TTB */
|
||||||
|
SEG_INIT_DATA static UINT32 g_cpgForPageTables = 0; /* number of pages being used for page tables */
|
||||||
|
SEG_INIT_DATA static UINT32 g_ctblFreeonLastPage = 0; /* number of page tables free on last page */
|
||||||
|
SEG_INIT_DATA static PPAGETAB g_ptblNext = NULL; /* pointer to next free page table */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Morphs the "flags" bits used for a page table entry in the TTB and for a page entry in the page table
|
||||||
|
* into the "flags" bits used for a section entry in the TTB.
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* - uiTableFlags = Flag bits that would be used for a page table entry in the TTB.
|
||||||
|
* - uiPageFlags = Flag bits that would be used for a page entry in the page table.
|
||||||
|
*
|
||||||
|
* Returns:
|
||||||
|
* The flag bits that would be used for a section entry in the TTB. If a bit or option is set
|
||||||
|
* in either uiTableFlags or uiPageFlags, it will be set in the appropriate place in the result.
|
||||||
|
*/
|
||||||
|
SEG_INIT_CODE static UINT32 make_section_flags(UINT32 uiTableFlags, UINT32 uiPageFlags)
|
||||||
|
{
|
||||||
|
register UINT32 rc = TTBSEC_ALWAYS;
|
||||||
|
rc |= ((uiTableFlags & TTBPGTBL_PXN) >> 2);
|
||||||
|
rc |= ((uiTableFlags & TTBPGTBL_NS) << 16);
|
||||||
|
rc |= (uiTableFlags & TTBPGTBL_DOM_MASK);
|
||||||
|
rc |= (uiTableFlags & TTBPGTBL_P);
|
||||||
|
rc |= ((uiPageFlags & PGTBLSM_XN) << 4);
|
||||||
|
rc |= (uiPageFlags & PGTBLSM_B);
|
||||||
|
rc |= (uiPageFlags & PGTBLSM_C);
|
||||||
|
rc |= ((uiPageFlags & PGTBLSM_AP) << 6);
|
||||||
|
rc |= ((uiPageFlags & PGTBLSM_TEX) << 6);
|
||||||
|
rc |= ((uiPageFlags & PGTBLSM_APX) << 6);
|
||||||
|
rc |= ((uiPageFlags & PGTBLSM_S) << 6);
|
||||||
|
rc |= ((uiPageFlags & PGTBLSM_NG) << 6);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Allocates page mapping entries within a single current entry in the TTB.
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* - paBase = The page-aligned base physical address to map.
|
||||||
|
* - pTTBEntry = Pointer to the TTB entry to be used.
|
||||||
|
* - ndxPage = The "first" index within the current page to use.
|
||||||
|
* - cpg = The maximum number of pages we want to map. This function will only map as many pages as will
|
||||||
|
* fit in the current TTB entry, as indicated by ndxPage.
|
||||||
|
* - uiTableFlags = Flags to be used or verified for the TTB entry.
|
||||||
|
* - uiPageFlags = Flags to be used for new page table entries.
|
||||||
|
*
|
||||||
|
* Returns:
|
||||||
|
* The number of pages that were actually mapped by this function call, or -1 if there was an error in the mapping.
|
||||||
|
*
|
||||||
|
* Side effects:
|
||||||
|
* May modify the ndxTTB'th entry in the TTB, if it was not previously allocated. May modify the current page
|
||||||
|
* table that the TTB entry points to, where applicable. If we need to allocate a new page table, may modify the
|
||||||
|
* global variables g_cpgForPageTables, g_ctblFreeonLastPage, and g_ptblNext.
|
||||||
|
*/
|
||||||
|
SEG_INIT_CODE static INT32 alloc_pages(PHYSADDR paBase, PTTB pTTBEntry, INT32 ndxPage, INT32 cpg, UINT32 uiTableFlags,
|
||||||
|
UINT32 uiPageFlags)
|
||||||
|
{
|
||||||
|
INT32 cpgCurrent; /* number of pages we're mapping */
|
||||||
|
PPAGETAB pTab; /* pointer to current or new page table */
|
||||||
|
register INT32 i; /* loop counter */
|
||||||
|
|
||||||
|
switch (pTTBEntry->data & TTBQUERY_MASK)
|
||||||
|
{
|
||||||
|
case TTBQUERY_FAULT: /* not allocated, allocate a new page table for the slot */
|
||||||
|
if (g_ctblFreeonLastPage == 0)
|
||||||
|
{
|
||||||
|
g_cpgForPageTables++;
|
||||||
|
g_ctblFreeonLastPage = 2;
|
||||||
|
}
|
||||||
|
g_ctblFreeonLastPage--;
|
||||||
|
pTab = g_ptblNext++;
|
||||||
|
for (i=0; i<SYS_PGTBL_ENTRIES; i++)
|
||||||
|
{
|
||||||
|
pTab->pgtbl[i].data = 0; /* blank out the new page table */
|
||||||
|
pTab->pgaux[i].data = 0;
|
||||||
|
}
|
||||||
|
pTTBEntry->data = ((UINT32)pTab) | uiTableFlags; /* poke new entry */
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TTBQUERY_PGTBL: /* existing page table */
|
||||||
|
if ((pTTBEntry->data & TTBPGTBL_ALLFLAGS) != uiTableFlags)
|
||||||
|
return -1; /* table flags not compatible */
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TTBQUERY_SEC:
|
||||||
|
case TTBQUERY_PXNSEC:
|
||||||
|
/* existing section, deal with this later */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Figure out how many entries we're going to map. */
|
||||||
|
cpgCurrent = SYS_PGTBL_ENTRIES - ndxPage; /* total free slots on page */
|
||||||
|
if (cpg < cpgCurrent)
|
||||||
|
cpgCurrent = cpg; /* only map up to max requested */
|
||||||
|
|
||||||
|
if (pTTBEntry->data & TTBSEC_ALWAYS)
|
||||||
|
{
|
||||||
|
/* this is a section, make sure its base address covers this mapping and its flags are compatible */
|
||||||
|
if ((pTTBEntry->data & TTBSEC_ALLFLAGS) != make_section_flags(uiTableFlags, uiPageFlags))
|
||||||
|
return -1;
|
||||||
|
if ((pTTBEntry->data & TTBSEC_BASE) != (paBase & TTBSEC_BASE))
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* fill in entries in the page table */
|
||||||
|
pTab = (PPAGETAB)(pTTBEntry->data & TTBPGTBL_BASE);
|
||||||
|
for (i=0; i<cpgCurrent; i++)
|
||||||
|
{
|
||||||
|
if ((pTab->pgtbl[ndxPage + i].data & PGQUERY_MASK) != PGQUERY_FAULT)
|
||||||
|
return -1; /* stepping on existing mapping */
|
||||||
|
pTab->pgtbl[ndxPage + i].data = paBase | uiPageFlags;
|
||||||
|
pTab->pgaux[ndxPage + i].data = 0; /* TODO */
|
||||||
|
paBase += SYS_PAGE_SIZE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return cpgCurrent;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Maps a certain number of memory pages beginning at a specified physical address into virtual memory
|
||||||
|
* beginning at a specified virtual address.
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* - paBase = The page-aligned base physical address to map.
|
||||||
|
* - vmaBase = The page-aligned virtual address to map those pages to.
|
||||||
|
* - cpg = The number of pages to be mapped.
|
||||||
|
* - uiTableFlags = Flags to be used or verified for TTB entries.
|
||||||
|
* - uiPageFlags = Flags to be used for new page table entries.
|
||||||
|
*
|
||||||
|
* Returns:
|
||||||
|
* TRUE if the mapping succeeded, FALSE if it failed.
|
||||||
|
*
|
||||||
|
* Side effects:
|
||||||
|
* May modify unallocated entries in the TTB. May modify any page tables that are pointed to by TTB entries,
|
||||||
|
* where applicable. If we need to allocate new page tables, may modify the global variables g_cpgForPageTables,
|
||||||
|
* g_ctblFreeonLastPage, and g_ptblNext.
|
||||||
|
*/
|
||||||
|
SEG_INIT_CODE static BOOL map_pages(PHYSADDR paBase, KERNADDR vmaBase, INT32 cpg, UINT32 uiTableFlags,
|
||||||
|
UINT32 uiPageFlags)
|
||||||
|
{
|
||||||
|
static DECLARE_INIT_STRING8_CONST(sz1, "Map ");
|
||||||
|
static DECLARE_INIT_STRING8_CONST(sz2, "->");
|
||||||
|
static DECLARE_INIT_STRING8_CONST(sz3, ",cpg=");
|
||||||
|
static DECLARE_INIT_STRING8_CONST(sz4, ",tf=");
|
||||||
|
static DECLARE_INIT_STRING8_CONST(sz5, ",pf=");
|
||||||
|
INT32 ndxTTB = mmVMA2TTBIndex(vmaBase); /* TTB entry index */
|
||||||
|
INT32 ndxPage = mmVMA2PGTBLIndex(vmaBase); /* starting page entry index */
|
||||||
|
INT32 cpgCurrent; /* current number of pages mapped */
|
||||||
|
|
||||||
|
ETrWriteString8(sz1);
|
||||||
|
ETrWriteWord(paBase);
|
||||||
|
ETrWriteString8(sz2);
|
||||||
|
ETrWriteWord(vmaBase);
|
||||||
|
ETrWriteString8(sz3);
|
||||||
|
ETrWriteWord(cpg);
|
||||||
|
ETrWriteString8(sz4);
|
||||||
|
ETrWriteWord(uiTableFlags);
|
||||||
|
ETrWriteString8(sz5);
|
||||||
|
ETrWriteWord(uiPageFlags);
|
||||||
|
ETrWriteChar8('\n');
|
||||||
|
|
||||||
|
if ((cpg > 0) && (ndxPage > 0))
|
||||||
|
{
|
||||||
|
/* We are starting in the middle of a VM page. Map to the end of the VM page. */
|
||||||
|
cpgCurrent = alloc_pages(paBase, g_pTTB + ndxTTB, ndxPage, cpg, uiTableFlags, uiPageFlags);
|
||||||
|
if (cpgCurrent < 0)
|
||||||
|
{
|
||||||
|
/* ETrWriteChar8('a'); */
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
/* adjust base physical address, page count, and TTB index */
|
||||||
|
paBase += (cpgCurrent << SYS_PAGE_BITS);
|
||||||
|
cpg -= cpgCurrent;
|
||||||
|
ndxTTB++;
|
||||||
|
/* N.B.: from this point on ndxPage will be treated as 0 */
|
||||||
|
}
|
||||||
|
while (cpg >= SYS_PGTBL_ENTRIES)
|
||||||
|
{
|
||||||
|
/* try to map a whole section's worth at a time */
|
||||||
|
if ((paBase & TTBSEC_BASE) == paBase)
|
||||||
|
{
|
||||||
|
/* paBase is section-aligned now as well, we can use a direct 1Mb section mapping */
|
||||||
|
switch (g_pTTB[ndxTTB].data & TTBQUERY_MASK)
|
||||||
|
{
|
||||||
|
case TTBQUERY_FAULT: /* unmapped - map the section */
|
||||||
|
g_pTTB[ndxTTB].data = paBase | make_section_flags(uiTableFlags, uiPageFlags);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TTBQUERY_PGTBL: /* collided with a page table */
|
||||||
|
/* ETrWriteChar8('b'); */
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
case TTBQUERY_SEC: /* test existing section */
|
||||||
|
case TTBQUERY_PXNSEC:
|
||||||
|
if ((g_pTTB[ndxTTB].data & TTBSEC_ALLFLAGS) != make_section_flags(uiTableFlags, uiPageFlags))
|
||||||
|
{
|
||||||
|
/* ETrWriteChar8('c'); */
|
||||||
|
return FALSE; /* invalid flags */
|
||||||
|
}
|
||||||
|
if ((g_pTTB[ndxTTB].data & TTBSEC_BASE) != paBase)
|
||||||
|
{
|
||||||
|
/* ETrWriteChar8('d'); */
|
||||||
|
return FALSE; /* invalid base address */
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
cpgCurrent = SYS_PGTBL_ENTRIES; /* we mapped a whole section worth */
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* just map 256 individual pages */
|
||||||
|
cpgCurrent = alloc_pages(paBase, g_pTTB + ndxTTB, 0, cpg, uiTableFlags, uiPageFlags);
|
||||||
|
if (cpgCurrent < 0)
|
||||||
|
{
|
||||||
|
/* ETrWriteChar8('e'); */
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* adjust base physical address, page count, and TTB index */
|
||||||
|
paBase += (cpgCurrent << SYS_PAGE_BITS);
|
||||||
|
cpg -= cpgCurrent;
|
||||||
|
ndxTTB++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cpg > 0)
|
||||||
|
{
|
||||||
|
/* map the "tail end" onto the next TTB */
|
||||||
|
if (alloc_pages(paBase, g_pTTB + ndxTTB, 0, cpg, uiTableFlags, uiPageFlags) < 0)
|
||||||
|
{
|
||||||
|
/* ETrWriteChar8('f'); */
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* External references to symbols defined by the linker script. */
|
||||||
|
extern char paFirstFree, cpgPrestartTotal, paLibraryCode, vmaLibraryCode, cpgLibraryCode, paKernelCode,
|
||||||
|
vmaKernelCode, cpgKernelCode, paKernelData, vmaKernelData, cpgKernelData, cpgKernelBss, paInitCode,
|
||||||
|
vmaInitCode, cpgInitCode, paInitData, vmaInitData, cpgInitData, cpgInitBss, vmaFirstFree;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initializes a TTB (used as TTB1 and initially TTB0 as well) with mappings to all the pieces of the kernel and
|
||||||
|
* to memory-mapped IO, and fills in details in the startup info structure.
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* - pstartup - Pointer to startup info structure, which is modified by this function.
|
||||||
|
*
|
||||||
|
* Returns:
|
||||||
|
* - Physical address of the new TTB1.
|
||||||
|
*
|
||||||
|
* Side effects:
|
||||||
|
* Modifies physical memory beyond the end of the kernel to store TTB and page tables. Uses several
|
||||||
|
* static globals in this module for work space while performing memory mappings.
|
||||||
|
*/
|
||||||
|
SEG_INIT_CODE PHYSADDR EMmInit(PSTARTUP_INFO pstartup)
|
||||||
|
{
|
||||||
|
static DECLARE_INIT_STRING8_CONST(szTTBAt, "EMmInit: TTB1@");
|
||||||
|
static DECLARE_INIT_STRING8_CONST(szPageTable, "Page table pages:");
|
||||||
|
static DECLARE_INIT_STRING8_CONST(szFree, "\nFree last page:");
|
||||||
|
PHYSADDR paTTB = (PHYSADDR)(&paFirstFree); /* location of the system TTB1 */
|
||||||
|
UINT32 cbMPDB; /* number of bytes in the MPDB */
|
||||||
|
register INT32 i; /* loop counter */
|
||||||
|
|
||||||
|
/* Locate the appropriate place for TTB1, on a 16K boundary. */
|
||||||
|
pstartup->cpgTTBGap = 0;
|
||||||
|
while (paTTB & (SYS_TTB1_SIZE - 1))
|
||||||
|
{
|
||||||
|
paTTB += SYS_PAGE_SIZE;
|
||||||
|
pstartup->cpgTTBGap++;
|
||||||
|
}
|
||||||
|
|
||||||
|
ETrWriteString8(szTTBAt);
|
||||||
|
ETrWriteWord(paTTB);
|
||||||
|
ETrWriteChar8('\n');
|
||||||
|
|
||||||
|
/* Save off the TTB location and initialize it. */
|
||||||
|
pstartup->paTTB = paTTB;
|
||||||
|
g_pTTB = (PTTB)paTTB;
|
||||||
|
for (i=0; i<SYS_TTB1_ENTRIES; i++)
|
||||||
|
g_pTTB[i].data = 0;
|
||||||
|
|
||||||
|
/* Allocate space for the Master Page Database but do not initialize it. */
|
||||||
|
pstartup->paMPDB = paTTB + SYS_TTB1_SIZE;
|
||||||
|
cbMPDB = pstartup->cpgSystemTotal << 2;
|
||||||
|
pstartup->cpgMPDB = cbMPDB >> SYS_PAGE_BITS;
|
||||||
|
if (cbMPDB & (SYS_PAGE_SIZE - 1))
|
||||||
|
{
|
||||||
|
pstartup->cpgMPDB++;
|
||||||
|
cbMPDB = pstartup->cpgMPDB << SYS_PAGE_BITS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Initialize the "next page table" pointer. */
|
||||||
|
pstartup->paFirstPageTable = pstartup->paMPDB + cbMPDB;
|
||||||
|
g_ptblNext = (PPAGETAB)(pstartup->paFirstPageTable);
|
||||||
|
|
||||||
|
/* Map the "prestart" area (everything below load address, plus prestart code & data) as identity. */
|
||||||
|
VERIFY(map_pages(0, 0, (INT32)(&cpgPrestartTotal), TTBPGTBL_ALWAYS, PGTBLSM_ALWAYS | PGTBLSM_AP01));
|
||||||
|
/* Map the IO area as identity. */
|
||||||
|
VERIFY(map_pages(PHYSADDR_IO_BASE, PHYSADDR_IO_BASE, PAGE_COUNT_IO, TTBPGTBL_ALWAYS, PGTBLSM_ALWAYS | PGTBLSM_AP01));
|
||||||
|
/* Map the library area. */
|
||||||
|
VERIFY(map_pages((PHYSADDR)(&paLibraryCode), (KERNADDR)(&vmaLibraryCode), (INT32)(&cpgLibraryCode),
|
||||||
|
TTBPGTBL_ALWAYS, PGTBLSM_ALWAYS | PGTBLSM_B | PGTBLSM_C | PGTBLSM_AP10));
|
||||||
|
/* Map the kernel code area. */
|
||||||
|
VERIFY(map_pages((PHYSADDR)(&paKernelCode), (KERNADDR)(&vmaKernelCode), (INT32)(&cpgKernelCode),
|
||||||
|
TTBPGTBL_ALWAYS, PGTBLSM_ALWAYS | PGTBLSM_B | PGTBLSM_C | PGTBLSM_AP01));
|
||||||
|
/* Map the kernel data/BSS area. */
|
||||||
|
VERIFY(map_pages((PHYSADDR)(&paKernelData), (KERNADDR)(&vmaKernelData),
|
||||||
|
(INT32)(&cpgKernelData) + (INT32)(&cpgKernelBss),
|
||||||
|
TTBPGTBL_ALWAYS, PGTBLSM_XN | PGTBLSM_ALWAYS | PGTBLSM_B | PGTBLSM_C | PGTBLSM_AP01));
|
||||||
|
/* Map the kernel init code area. */
|
||||||
|
VERIFY(map_pages((PHYSADDR)(&paInitCode), (KERNADDR)(&vmaInitCode), (INT32)(&cpgInitCode),
|
||||||
|
TTBPGTBL_ALWAYS, PGTBLSM_ALWAYS | PGTBLSM_B | PGTBLSM_C | PGTBLSM_AP01));
|
||||||
|
/* Map the kernel init data/BSS area. */
|
||||||
|
VERIFY(map_pages((PHYSADDR)(&paInitData), (KERNADDR)(&vmaInitData),
|
||||||
|
(INT32)(&cpgInitData) + (INT32)(&cpgInitBss),
|
||||||
|
TTBPGTBL_ALWAYS, PGTBLSM_XN | PGTBLSM_ALWAYS | PGTBLSM_B | PGTBLSM_C | PGTBLSM_AP01));
|
||||||
|
/* Map the TTB itself. */
|
||||||
|
pstartup->kaTTB = (KERNADDR)(&vmaFirstFree);
|
||||||
|
VERIFY(map_pages(paTTB, pstartup->kaTTB, SYS_TTB1_SIZE / SYS_PAGE_SIZE,
|
||||||
|
TTBPGTBL_ALWAYS, PGTBLSM_XN | PGTBLSM_ALWAYS | PGTBLSM_B | PGTBLSM_C | PGTBLSM_AP01));
|
||||||
|
/* Map the Master Page Database. */
|
||||||
|
pstartup->kaMPDB = pstartup->kaTTB + SYS_TTB1_SIZE;
|
||||||
|
VERIFY(map_pages(pstartup->paMPDB, pstartup->kaTTB + SYS_TTB1_SIZE, pstartup->cpgMPDB,
|
||||||
|
TTBPGTBL_ALWAYS, PGTBLSM_XN | PGTBLSM_ALWAYS | PGTBLSM_B | PGTBLSM_C | PGTBLSM_AP01));
|
||||||
|
/* Map the IO area into high memory as well. */
|
||||||
|
VERIFY(map_pages(PHYSADDR_IO_BASE, VMADDR_IO_BASE, PAGE_COUNT_IO, TTBPGTBL_ALWAYS, PGTBLSM_ALWAYS | PGTBLSM_AP01));
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
/* Dump the TTB and page tables to trace output. */
|
||||||
|
ETrDumpWords((PUINT32)paTTB, (SYS_TTB1_SIZE + (g_cpgForPageTables << SYS_PAGE_BITS)) >> 2);
|
||||||
|
ETrWriteString8(szPageTable);
|
||||||
|
ETrWriteWord(g_cpgForPageTables);
|
||||||
|
ETrWriteString8(szFree);
|
||||||
|
ETrWriteWord(g_ctblFreeonLastPage);
|
||||||
|
ETrWriteChar8('\n');
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Fill in the rest of the data in the startup info structure. */
|
||||||
|
pstartup->cpgPageTables = g_cpgForPageTables;
|
||||||
|
pstartup->ctblFreeOnLastPage = g_ctblFreeonLastPage;
|
||||||
|
pstartup->paFirstFree = pstartup->paFirstPageTable + (g_cpgForPageTables << SYS_PAGE_BITS);
|
||||||
|
pstartup->vmaFirstFree = pstartup->kaMPDB + cbMPDB;
|
||||||
|
|
||||||
|
return paTTB; /* return this for startup ASM code to use */
|
||||||
|
}
|
245
kernel/early_trace.c
Normal file
245
kernel/early_trace.c
Normal file
|
@ -0,0 +1,245 @@
|
||||||
|
/*
|
||||||
|
* This file is part of the COMROGUE Operating System for Raspberry Pi
|
||||||
|
*
|
||||||
|
* Copyright (c) 2013, Eric J. Bowersox / Erbosoft Enterprises
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This program is free for commercial and non-commercial use as long as the following conditions are
|
||||||
|
* adhered to.
|
||||||
|
*
|
||||||
|
* Copyright in this file remains Eric J. Bowersox and/or Erbosoft, and as such any copyright notices
|
||||||
|
* in the code are not to be removed.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification, are permitted
|
||||||
|
* provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* * Redistributions of source code must retain the above copyright notice, this list of conditions and
|
||||||
|
* the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
|
||||||
|
* the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
|
||||||
|
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||||
|
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||||
|
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* "Raspberry Pi" is a trademark of the Raspberry Pi Foundation.
|
||||||
|
*/
|
||||||
|
#define __COMROGUE_PRESTART__
|
||||||
|
#include <comrogue/types.h>
|
||||||
|
#include <comrogue/internals/seg.h>
|
||||||
|
#include <comrogue/internals/llio.h>
|
||||||
|
#include <comrogue/internals/auxdev.h>
|
||||||
|
#include <comrogue/internals/gpio.h>
|
||||||
|
#include <comrogue/internals/16550.h>
|
||||||
|
#include <comrogue/internals/trace.h>
|
||||||
|
|
||||||
|
/* Hex digits. */
|
||||||
|
static DECLARE_INIT_STRING8_CONST(szHexDigits, "0123456789ABCDEF");
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initializes the trace functionality (the aux UART).
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* None.
|
||||||
|
*
|
||||||
|
* Returns:
|
||||||
|
* Nothing.
|
||||||
|
*
|
||||||
|
* Side effects:
|
||||||
|
* GPIO 14 configured for output from UART1; UART1 initialized to 115200 8N1 and enabled for output.
|
||||||
|
*/
|
||||||
|
SEG_INIT_CODE void ETrInit(void)
|
||||||
|
{
|
||||||
|
register UINT32 ra;
|
||||||
|
|
||||||
|
/* Initialize UART */
|
||||||
|
llIOWrite(AUX_REG_ENABLE, AUX_ENABLE_MU); /* enable UART1 */
|
||||||
|
llIOWrite(AUX_MU_REG_IER, 0);
|
||||||
|
llIOWrite(AUX_MU_REG_CNTL, 0);
|
||||||
|
llIOWrite(AUX_MU_REG_LCR, U16550_LCR_LENGTH_8|U16550_LCR_PARITY_NONE); /* 8 bits, no parity */
|
||||||
|
llIOWrite(AUX_MU_REG_MCR, 0);
|
||||||
|
llIOWrite(AUX_MU_REG_IER, 0);
|
||||||
|
llIOWrite(AUX_MU_REG_FCR, U16550_FCR_RXCLEAR|U16550_FCR_TXCLEAR|U16550_FCR_LEVEL_14);
|
||||||
|
llIOWrite(AUX_MU_REG_BAUD, 270); /* 115200 baud */
|
||||||
|
ra = llIORead(GPFSEL1_REG);
|
||||||
|
ra &= ~GP_FUNC_MASK(4); /* GPIO 14 - connects to pin 8 on GPIO connector */
|
||||||
|
ra |= GP_FUNC_BITS(4, GP_PIN_ALT5); /* Alt function 5 - UART1 TxD */
|
||||||
|
llIOWrite(GPFSEL1_REG, ra);
|
||||||
|
llIOWrite(GPPUD_REG, 0);
|
||||||
|
llIODelay(150);
|
||||||
|
llIOWrite(GPPUDCLK0_REG, GP_BIT(14));
|
||||||
|
llIODelay(150);
|
||||||
|
llIOWrite(GPPUDCLK0_REG, 0);
|
||||||
|
llIOWrite(AUX_MU_REG_CNTL, AUXMU_CNTL_TXENABLE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Writes a raw character to trace output.
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* - c = The character to be written.
|
||||||
|
*
|
||||||
|
* Returns:
|
||||||
|
* Nothing.
|
||||||
|
*
|
||||||
|
* Side effects:
|
||||||
|
* Character written to UART1.
|
||||||
|
*/
|
||||||
|
SEG_INIT_CODE static void write_trace(UINT32 c)
|
||||||
|
{
|
||||||
|
register UINT32 lsr = llIORead(AUX_MU_REG_LSR);
|
||||||
|
while (!(lsr & U16550_LSR_TXEMPTY))
|
||||||
|
lsr = llIORead(AUX_MU_REG_LSR);
|
||||||
|
llIOWrite(AUX_MU_REG_THR, c);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Writes a character to trace output, translating newlines.
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* - c = The character to be written.
|
||||||
|
*
|
||||||
|
* Returns:
|
||||||
|
* Nothing.
|
||||||
|
*
|
||||||
|
* Side effects:
|
||||||
|
* Either 1 or 2 characters written to UART1.
|
||||||
|
*/
|
||||||
|
SEG_INIT_CODE void ETrWriteChar8(CHAR c)
|
||||||
|
{
|
||||||
|
if (c == '\n')
|
||||||
|
write_trace('\r');
|
||||||
|
write_trace((UINT32)c);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Writes a null-terminated string to trace output. Newlines in the string are translated.
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* - psz = Pointer to string to be written.
|
||||||
|
*
|
||||||
|
* Returns:
|
||||||
|
* Nothing.
|
||||||
|
*
|
||||||
|
* Side effects:
|
||||||
|
* Characters in string written to UART1.
|
||||||
|
*/
|
||||||
|
SEG_INIT_CODE void ETrWriteString8(PCSTR psz)
|
||||||
|
{
|
||||||
|
while (*psz)
|
||||||
|
ETrWriteChar8(*psz++);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Writes the value of a 32-bit word to trace output.
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* - uiValue = Value to be written to trace output.
|
||||||
|
*
|
||||||
|
* Returns:
|
||||||
|
* Nothing.
|
||||||
|
*
|
||||||
|
* Side effects:
|
||||||
|
* 8 characters written to UART1.
|
||||||
|
*/
|
||||||
|
SEG_INIT_CODE void ETrWriteWord(UINT32 uiValue)
|
||||||
|
{
|
||||||
|
register UINT32 uiShift = 32;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
uiShift -= 4;
|
||||||
|
write_trace(szHexDigits[(uiValue >> uiShift) & 0xF]);
|
||||||
|
} while (uiShift > 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Dumps the values of memory words beginning at a specified address.
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* - puiWords = Pointer to words to be dumped.
|
||||||
|
* - cWords = Number of words to be dumped.
|
||||||
|
*
|
||||||
|
* Returns:
|
||||||
|
* Nothing.
|
||||||
|
*
|
||||||
|
* Side effects:
|
||||||
|
* Many characters written to UART1.
|
||||||
|
*/
|
||||||
|
SEG_INIT_CODE void ETrDumpWords(PUINT32 puiWords, UINT32 cWords)
|
||||||
|
{
|
||||||
|
static DECLARE_INIT_STRING8_CONST(szSpacer1, ": ");
|
||||||
|
register UINT32 i;
|
||||||
|
for (i = 0; i < cWords; i++)
|
||||||
|
{
|
||||||
|
if ((i & 0x3) == 0)
|
||||||
|
{
|
||||||
|
ETrWriteWord((UINT32)(puiWords + i));
|
||||||
|
ETrWriteString8(szSpacer1);
|
||||||
|
}
|
||||||
|
ETrWriteWord(puiWords[i]);
|
||||||
|
if ((i & 0x3) == 0x3)
|
||||||
|
ETrWriteChar8('\n');
|
||||||
|
else
|
||||||
|
ETrWriteChar8(' ');
|
||||||
|
}
|
||||||
|
if ((cWords & 0x3) != 0)
|
||||||
|
ETrWriteChar8('\n');
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Prints an "assertion failed" message to trace output.
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* - pszFile = The file name the assertion was declared in.
|
||||||
|
* - nLine = The line number the assertion was declared at.
|
||||||
|
*
|
||||||
|
* Returns:
|
||||||
|
* Nothing.
|
||||||
|
*
|
||||||
|
* Side effects:
|
||||||
|
* Characters written to UART1.
|
||||||
|
*/
|
||||||
|
SEG_INIT_CODE void ETrAssertFailed(PCSTR pszFile, INT32 nLine)
|
||||||
|
{
|
||||||
|
static DECLARE_INIT_STRING8_CONST(szPrefix, "** ASSERTION FAILED: ");
|
||||||
|
ETrWriteString8(szPrefix);
|
||||||
|
ETrWriteString8(pszFile);
|
||||||
|
write_trace(':');
|
||||||
|
ETrWriteWord((UINT32)nLine);
|
||||||
|
ETrWriteChar8('\n');
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Puts the CPU into a loop where it blinks the green ACTIVITY light forever.
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* None.
|
||||||
|
*
|
||||||
|
* Returns:
|
||||||
|
* DOES NOT RETURN!
|
||||||
|
*
|
||||||
|
* Side effects:
|
||||||
|
* GPIO 16 configured for output and turns on and off indefinitely.
|
||||||
|
*/
|
||||||
|
SEG_INIT_CODE void ETrInfiniBlink(void)
|
||||||
|
{
|
||||||
|
register UINT32 ra;
|
||||||
|
|
||||||
|
ra = llIORead(GPFSEL1_REG);
|
||||||
|
ra &= GP_FUNC_MASK(6); /* GPIO 16 - connects to green ACTIVITY LED */
|
||||||
|
ra |= GP_FUNC_BITS(6, GP_PIN_OUTPUT); /* output in all circumstances */
|
||||||
|
llIOWrite(GPFSEL1_REG, ra);
|
||||||
|
|
||||||
|
for(;;)
|
||||||
|
{
|
||||||
|
llIOWrite(GPSET0_REG, GP_BIT(16));
|
||||||
|
llIODelay(0x100000);
|
||||||
|
llIOWrite(GPCLR0_REG, GP_BIT(16));
|
||||||
|
llIODelay(0x100000);
|
||||||
|
}
|
||||||
|
}
|
81
kernel/intlib.c
Normal file
81
kernel/intlib.c
Normal file
|
@ -0,0 +1,81 @@
|
||||||
|
/*
|
||||||
|
* This file is part of the COMROGUE Operating System for Raspberry Pi
|
||||||
|
*
|
||||||
|
* Copyright (c) 2013, Eric J. Bowersox / Erbosoft Enterprises
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This program is free for commercial and non-commercial use as long as the following conditions are
|
||||||
|
* adhered to.
|
||||||
|
*
|
||||||
|
* Copyright in this file remains Eric J. Bowersox and/or Erbosoft, and as such any copyright notices
|
||||||
|
* in the code are not to be removed.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification, are permitted
|
||||||
|
* provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* * Redistributions of source code must retain the above copyright notice, this list of conditions and
|
||||||
|
* the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
|
||||||
|
* the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
|
||||||
|
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||||
|
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||||
|
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* "Raspberry Pi" is a trademark of the Raspberry Pi Foundation.
|
||||||
|
*/
|
||||||
|
#include <comrogue/types.h>
|
||||||
|
#include <comrogue/intlib.h>
|
||||||
|
#include <comrogue/internals/seg.h>
|
||||||
|
#include "quad.h"
|
||||||
|
|
||||||
|
/*---------------------------
|
||||||
|
* Integer library functions
|
||||||
|
*---------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Flags used internally to IntLDiv. */
|
||||||
|
#define FLIP_QUOTIENT 0x00000001
|
||||||
|
#define FLIP_REMAINDER 0x00000002
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Divides two 64-bit integers and returns a quotient and a remainder in a structure.
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* - pResult = Pointer to an LDIV structure to contain the quotient and remainder.
|
||||||
|
* - num = The numerator (dividend) for the division.
|
||||||
|
* - demom = The demoninator (divisor) for the division.
|
||||||
|
*
|
||||||
|
* Returns:
|
||||||
|
* Standard SUCCEEDED/FAILED HRESULT.
|
||||||
|
*/
|
||||||
|
SEG_LIB_CODE HRESULT IntLDiv(PLDIV pResult, INT64 num, INT64 denom)
|
||||||
|
{
|
||||||
|
UINT32 mode = 0;
|
||||||
|
if (denom == 0)
|
||||||
|
{
|
||||||
|
pResult->quot = pResult->rem = 0;
|
||||||
|
return E_INVALIDARG;
|
||||||
|
}
|
||||||
|
if (denom < 0)
|
||||||
|
{
|
||||||
|
mode ^= FLIP_QUOTIENT;
|
||||||
|
denom = -denom;
|
||||||
|
}
|
||||||
|
if (num < 0)
|
||||||
|
{
|
||||||
|
mode ^= (FLIP_QUOTIENT|FLIP_REMAINDER);
|
||||||
|
num = -num;
|
||||||
|
}
|
||||||
|
pResult->quot = __qdivrem(num, denom, (PUINT64)(&(pResult->rem)));
|
||||||
|
if (mode & FLIP_QUOTIENT)
|
||||||
|
pResult->quot = -(pResult->quot);
|
||||||
|
if (mode & FLIP_REMAINDER)
|
||||||
|
pResult->rem = -(pResult->rem);
|
||||||
|
return S_OK;
|
||||||
|
}
|
94
kernel/kistart.c
Normal file
94
kernel/kistart.c
Normal file
|
@ -0,0 +1,94 @@
|
||||||
|
/*
|
||||||
|
* This file is part of the COMROGUE Operating System for Raspberry Pi
|
||||||
|
*
|
||||||
|
* Copyright (c) 2013, Eric J. Bowersox / Erbosoft Enterprises
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This program is free for commercial and non-commercial use as long as the following conditions are
|
||||||
|
* adhered to.
|
||||||
|
*
|
||||||
|
* Copyright in this file remains Eric J. Bowersox and/or Erbosoft, and as such any copyright notices
|
||||||
|
* in the code are not to be removed.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification, are permitted
|
||||||
|
* provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* * Redistributions of source code must retain the above copyright notice, this list of conditions and
|
||||||
|
* the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
|
||||||
|
* the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
|
||||||
|
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||||
|
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||||
|
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* "Raspberry Pi" is a trademark of the Raspberry Pi Foundation.
|
||||||
|
*/
|
||||||
|
#define __COMROGUE_INIT__
|
||||||
|
#include <comrogue/types.h>
|
||||||
|
#include <comrogue/internals/seg.h>
|
||||||
|
#include <comrogue/internals/trace.h>
|
||||||
|
#include <comrogue/internals/startup.h>
|
||||||
|
#include <comrogue/internals/mmu.h>
|
||||||
|
|
||||||
|
#ifdef THIS_FILE
|
||||||
|
#undef THIS_FILE
|
||||||
|
DECLARE_THIS_FILE
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*--------------------------------------------------------------------------------------------------------
|
||||||
|
* Startup info buffer. Data is copied into here by the assembly code before KiSystemStartup is invoked.
|
||||||
|
*--------------------------------------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
SEG_INIT_DATA STARTUP_INFO kiStartupInfo; /* startup info buffer */
|
||||||
|
|
||||||
|
SEG_INIT_CODE static void dump_startup_info()
|
||||||
|
{
|
||||||
|
TrPrintf8("Mach type %x, revision %x, serial %x\n", kiStartupInfo.uiMachineType, kiStartupInfo.uiRevision,
|
||||||
|
kiStartupInfo.uiSerialNumber);
|
||||||
|
TrPrintf8("Memory: %u total pages (%u available), %u TTB gap\n", kiStartupInfo.cpgSystemTotal,
|
||||||
|
kiStartupInfo.cpgSystemAvail, kiStartupInfo.cpgTTBGap);
|
||||||
|
TrPrintf8("TTB1 @ PA %08X, VMA %08X\n", kiStartupInfo.paTTB, kiStartupInfo.kaTTB);
|
||||||
|
TrPrintf8("MPDB @ PA %08X, VMA %08X, %u pages\n", kiStartupInfo.paMPDB, kiStartupInfo.kaMPDB, kiStartupInfo.cpgMPDB);
|
||||||
|
TrPrintf8("Page tables @ PA %08X, %u pages, %u free on last one\n", kiStartupInfo.paFirstPageTable,
|
||||||
|
kiStartupInfo.cpgPageTables, kiStartupInfo.ctblFreeOnLastPage);
|
||||||
|
TrPrintf8("First free PA = %08X, first free VMA = %08X\n", kiStartupInfo.paFirstFree, kiStartupInfo.vmaFirstFree);
|
||||||
|
TrPrintf8("EMMC clock freq = %u\n", kiStartupInfo.uiEMMCClockFreq);
|
||||||
|
TrPrintf8("VC memory is at PHYS:%08X, %u bytes, framebuffer %ux%u\n", kiStartupInfo.paVCMem, kiStartupInfo.cbVCMem,
|
||||||
|
kiStartupInfo.cxFBWidth, kiStartupInfo.cyFBHeight);
|
||||||
|
TrPrintf8("MAC address %02X:%02X:%02X:%02X:%02X:%02X\n", kiStartupInfo.abMACAddress[0],
|
||||||
|
kiStartupInfo.abMACAddress[1], kiStartupInfo.abMACAddress[2], kiStartupInfo.abMACAddress[3],
|
||||||
|
kiStartupInfo.abMACAddress[4], kiStartupInfo.abMACAddress[5]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*---------------------
|
||||||
|
* System startup code
|
||||||
|
*---------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
static DECLARE_INIT_STRING8_CONST(banner, "--- COMROGUE %d.%02d\n- KiSystemStartup\n");
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Starts the COMROGUE Operating System.
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* None.
|
||||||
|
*
|
||||||
|
* Returns:
|
||||||
|
* DOES NOT RETURN!
|
||||||
|
*
|
||||||
|
* Side effects:
|
||||||
|
* Uses the information in kiStartupInfo.
|
||||||
|
*/
|
||||||
|
SEG_INIT_CODE void KiSystemStartup(void)
|
||||||
|
{
|
||||||
|
TrPrintf8(banner, 0, 0);
|
||||||
|
dump_startup_info();
|
||||||
|
TrInfiniBlink();
|
||||||
|
}
|
96
kernel/lowlevel.S
Normal file
96
kernel/lowlevel.S
Normal file
|
@ -0,0 +1,96 @@
|
||||||
|
/*
|
||||||
|
* This file is part of the COMROGUE Operating System for Raspberry Pi
|
||||||
|
*
|
||||||
|
* Copyright (c) 2013, Eric J. Bowersox / Erbosoft Enterprises
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This program is free for commercial and non-commercial use as long as the following conditions are
|
||||||
|
* adhered to.
|
||||||
|
*
|
||||||
|
* Copyright in this file remains Eric J. Bowersox and/or Erbosoft, and as such any copyright notices
|
||||||
|
* in the code are not to be removed.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification, are permitted
|
||||||
|
* provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* * Redistributions of source code must retain the above copyright notice, this list of conditions and
|
||||||
|
* the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
|
||||||
|
* the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
|
||||||
|
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||||
|
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||||
|
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* "Raspberry Pi" is a trademark of the Raspberry Pi Foundation.
|
||||||
|
*/
|
||||||
|
.section ".text"
|
||||||
|
|
||||||
|
/*------------------------
|
||||||
|
* Low-level IO functions
|
||||||
|
*------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Writes a 32-bit word of data to a memory-mapped IO port.
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* - kaPort = Kernel address of the IO port to write to.
|
||||||
|
* - uiData = Data to be written.
|
||||||
|
*
|
||||||
|
* Returns:
|
||||||
|
* Nothing.
|
||||||
|
*
|
||||||
|
* Side effects:
|
||||||
|
* Writing to any given IO port may have arbitrary side effects.
|
||||||
|
*/
|
||||||
|
.globl llIOWriteK
|
||||||
|
llIOWriteK:
|
||||||
|
str r1,[r0]
|
||||||
|
bx lr
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Reads a 32-bit word of data from a memory-mapped IO port.
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* - kaPort = Kernel address of the IO port we read from.
|
||||||
|
*
|
||||||
|
* Returns:
|
||||||
|
* The word of data read from the IO port.
|
||||||
|
*
|
||||||
|
* Side effects:
|
||||||
|
* Reading from any given IO port may have arbitrary side effects.
|
||||||
|
*/
|
||||||
|
.globl llIOReadK
|
||||||
|
llIOReadK:
|
||||||
|
ldr r0,[r0]
|
||||||
|
bx lr
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Delays for a certain number of cycles, to allow an IO operation to work.
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* - uiTicks = The number of "ticks" to delay.
|
||||||
|
*
|
||||||
|
* Returns:
|
||||||
|
* Nothing.
|
||||||
|
*/
|
||||||
|
.globl llIODelay
|
||||||
|
llIODelay:
|
||||||
|
push {lr}
|
||||||
|
.delaytop:
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
bl .delayreturn
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
subs r0, r0, #1
|
||||||
|
bne .delaytop
|
||||||
|
pop {lr}
|
||||||
|
.delayreturn:
|
||||||
|
bx lr
|
271
kernel/prestart.S
Normal file
271
kernel/prestart.S
Normal file
|
@ -0,0 +1,271 @@
|
||||||
|
/*
|
||||||
|
* This file is part of the COMROGUE Operating System for Raspberry Pi
|
||||||
|
*
|
||||||
|
* Copyright (c) 2013, Eric J. Bowersox / Erbosoft Enterprises
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This program is free for commercial and non-commercial use as long as the following conditions are
|
||||||
|
* adhered to.
|
||||||
|
*
|
||||||
|
* Copyright in this file remains Eric J. Bowersox and/or Erbosoft, and as such any copyright notices
|
||||||
|
* in the code are not to be removed.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification, are permitted
|
||||||
|
* provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* * Redistributions of source code must retain the above copyright notice, this list of conditions and
|
||||||
|
* the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
|
||||||
|
* the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
|
||||||
|
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||||
|
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||||
|
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* "Raspberry Pi" is a trademark of the Raspberry Pi Foundation.
|
||||||
|
*/
|
||||||
|
#define __COMROGUE_PRESTART__
|
||||||
|
#include <comrogue/internals/asm-macros.h>
|
||||||
|
#include <comrogue/internals/layout.h>
|
||||||
|
#include <comrogue/internals/mmu.h>
|
||||||
|
#include <comrogue/internals/sctlr.h>
|
||||||
|
|
||||||
|
/*------------------------------------------------------------------------------------------
|
||||||
|
* The prestart code that gets control when the kernel is first loaded; its objective is to
|
||||||
|
* set up the MMU and hand over control to the actual start code.
|
||||||
|
*------------------------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
.section ".prestartHEAD.text"
|
||||||
|
|
||||||
|
.globl COMROGUEPrestart
|
||||||
|
|
||||||
|
/* On entry: r0 = 0, r1 = machine type, r2 = atags address */
|
||||||
|
COMROGUEPrestart:
|
||||||
|
/* Initialize a temporary stack area. */
|
||||||
|
mov ip, # PHYSADDR_LOAD
|
||||||
|
sub sp, ip, #4
|
||||||
|
|
||||||
|
/* Go collect the startup info. */
|
||||||
|
bl KiCollectStartupInfo
|
||||||
|
mov r11, r0 /* r11 = address of startup info structure */
|
||||||
|
/* at this point r0-r2 are free for other code to use */
|
||||||
|
|
||||||
|
/* Early trace initialize; we reinitialize it later. */
|
||||||
|
bl ETrInit
|
||||||
|
ldr r0, =.initMessage
|
||||||
|
bl ETrWriteString8
|
||||||
|
|
||||||
|
/* Copy the early vector table into place, including the vector words that live after the table itself. */
|
||||||
|
ldr r0, =.earlyVectorTable
|
||||||
|
ldr r1, =.earlyVectorTableEnd
|
||||||
|
mov r2, #0
|
||||||
|
b .vec1
|
||||||
|
.vec0:
|
||||||
|
ldm r0!, {r3-r6} /* copy 16 bytes at a time */
|
||||||
|
stm r2!, {r3-r6}
|
||||||
|
.vec1:
|
||||||
|
cmp r0, r1
|
||||||
|
bne .vec0
|
||||||
|
|
||||||
|
/* Initialize early memory management (the TTB1). */
|
||||||
|
mov r0, r11
|
||||||
|
bl EMmInit
|
||||||
|
mov r10, r0 /* r10 = address of TTB */
|
||||||
|
|
||||||
|
/* Set up and start the MMU. */
|
||||||
|
mov ip, #0
|
||||||
|
mcr p15, 0, ip, c7, c7, 0 /* clear caches */
|
||||||
|
mcr p15, 0, ip, c8, c7, 0 /* clear TLB */
|
||||||
|
mov ip, #1
|
||||||
|
mcr p15, 0, ip, c2, c0, 2 /* set TTBCR */
|
||||||
|
mvn ip, #0
|
||||||
|
mcr p15, 0, ip, c3, c0, 0 /* configure domain 0 = client, all others = invalid */
|
||||||
|
mcr p15, 0, r10, c2, c0, 0 /* set TTB0 */
|
||||||
|
mcr p15, 0, r10, c2, c0, 1 /* set TTB1 */
|
||||||
|
|
||||||
|
mrc p15, 0, ip, c1, c0, 0 /* get control register 1 */
|
||||||
|
orr ip, ip, # SCTLR_M /* MMU = on */
|
||||||
|
orr ip, ip, # SCTLR_XP /* subpage AP bits disabled in 2nd-level page tables */
|
||||||
|
|
||||||
|
instr_barrier
|
||||||
|
mcr p15, 0, ip, c1, c0, 0 /* store control register 1 */
|
||||||
|
mrc p15, 0, ip, c0, c0, 0 /* read ID register */
|
||||||
|
instr_barrier
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
ldr r0, =.msg1
|
||||||
|
bl ETrWriteString8
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* now go to the start area in kernel space */
|
||||||
|
mov r0, r11
|
||||||
|
ldr ip, =COMROGUEStart
|
||||||
|
mov pc, ip
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
.balign 4
|
||||||
|
.msg1:
|
||||||
|
.asciz "got here 1\n"
|
||||||
|
.balign 4
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*-------------------------------------------------------------
|
||||||
|
* Early exception-handler code, mainly for debugging purposes
|
||||||
|
*-------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
.earlyReset:
|
||||||
|
ldr r0, =.resetMessage
|
||||||
|
b .earlyFUBAR
|
||||||
|
.earlyUndef:
|
||||||
|
ldr r0, =.undefMessage
|
||||||
|
b .earlyFUBAR
|
||||||
|
.earlySVC:
|
||||||
|
ldr r0, =.svcMessage
|
||||||
|
b .earlyFUBAR
|
||||||
|
.earlyPrefetch:
|
||||||
|
ldr r0, =.prefetchMessage
|
||||||
|
b .earlyFUBAR
|
||||||
|
.earlyData:
|
||||||
|
ldr r0, =.dataMessage
|
||||||
|
b .earlyFUBAR
|
||||||
|
.earlyHyp:
|
||||||
|
ldr r0, =.hypMessage
|
||||||
|
b .earlyFUBAR
|
||||||
|
.earlyIRQ:
|
||||||
|
ldr r0, =.irqMessage
|
||||||
|
b .earlyFUBAR
|
||||||
|
.earlyFIQ:
|
||||||
|
ldr r0, =.fiqMessage
|
||||||
|
.earlyFUBAR:
|
||||||
|
bl ETrWriteString8
|
||||||
|
.hang:
|
||||||
|
wfe
|
||||||
|
b .hang
|
||||||
|
|
||||||
|
.earlyVectorTable:
|
||||||
|
ldr pc, .resetVector
|
||||||
|
ldr pc, .undefVector
|
||||||
|
ldr pc, .svcVector
|
||||||
|
ldr pc, .prefetchVector
|
||||||
|
ldr pc, .dataVector
|
||||||
|
ldr pc, .hypVector
|
||||||
|
ldr pc, .irqVector
|
||||||
|
ldr pc, .fiqVector
|
||||||
|
.resetVector:
|
||||||
|
.word .earlyReset
|
||||||
|
.undefVector:
|
||||||
|
.word .earlyUndef
|
||||||
|
.svcVector:
|
||||||
|
.word .earlySVC
|
||||||
|
.prefetchVector:
|
||||||
|
.word .earlyPrefetch
|
||||||
|
.dataVector:
|
||||||
|
.word .earlyData
|
||||||
|
.hypVector:
|
||||||
|
.word .earlyHyp
|
||||||
|
.irqVector:
|
||||||
|
.word .earlyIRQ
|
||||||
|
.fiqVector:
|
||||||
|
.word .earlyFIQ
|
||||||
|
.earlyVectorTableEnd:
|
||||||
|
|
||||||
|
.balign 4
|
||||||
|
.initMessage:
|
||||||
|
.asciz "COMROGUEPrestart\n"
|
||||||
|
.balign 4
|
||||||
|
.resetMessage:
|
||||||
|
.asciz "+++ RESET!!!\n"
|
||||||
|
.balign 4
|
||||||
|
.undefMessage:
|
||||||
|
.asciz "+++ UNDEF!!!\n"
|
||||||
|
.balign 4
|
||||||
|
.svcMessage:
|
||||||
|
.asciz "+++ SVC!!!\n"
|
||||||
|
.balign 4
|
||||||
|
.prefetchMessage:
|
||||||
|
.asciz "+++ PREFETCH!!!\n"
|
||||||
|
.balign 4
|
||||||
|
.dataMessage:
|
||||||
|
.asciz "+++ DATA!!!\n"
|
||||||
|
.balign 4
|
||||||
|
.hypMessage:
|
||||||
|
.asciz "+++ HYP!!!\n"
|
||||||
|
.balign 4
|
||||||
|
.irqMessage:
|
||||||
|
.asciz "+++ IRQ!!!\n"
|
||||||
|
.balign 4
|
||||||
|
.fiqMessage:
|
||||||
|
.asciz "+++ FIQ!!!\n"
|
||||||
|
|
||||||
|
/*--------------------------------------------------------------------------------------
|
||||||
|
* Low-level IO functions that are placed here to make them callable from prestart code
|
||||||
|
*--------------------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
.section ".prestart.text"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Writes a 32-bit word of data to a memory-mapped IO port.
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* - paPort = Physical address of the IO port to write to.
|
||||||
|
* - uiData = Data to be written.
|
||||||
|
*
|
||||||
|
* Returns:
|
||||||
|
* Nothing.
|
||||||
|
*
|
||||||
|
* Side effects:
|
||||||
|
* Writing to any given IO port may have arbitrary side effects.
|
||||||
|
*/
|
||||||
|
.globl llIOWritePA
|
||||||
|
llIOWritePA:
|
||||||
|
str r1,[r0]
|
||||||
|
bx lr
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Reads a 32-bit word of data from a memory-mapped IO port.
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* - paPort = Physical address of the IO port we read from.
|
||||||
|
*
|
||||||
|
* Returns:
|
||||||
|
* The word of data read from the IO port.
|
||||||
|
*
|
||||||
|
* Side effects:
|
||||||
|
* Reading from any given IO port may have arbitrary side effects.
|
||||||
|
*/
|
||||||
|
.globl llIOReadPA
|
||||||
|
llIOReadPA:
|
||||||
|
ldr r0,[r0]
|
||||||
|
bx lr
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Delays for a certain number of cycles, to allow an IO operation to work.
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* - uiTicks = The number of "ticks" to delay.
|
||||||
|
*
|
||||||
|
* Returns:
|
||||||
|
* Nothing.
|
||||||
|
*/
|
||||||
|
.globl llIODelayPA
|
||||||
|
llIODelayPA:
|
||||||
|
push {lr}
|
||||||
|
.delaytop:
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
bl .delayreturn
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
subs r0, r0, #1
|
||||||
|
bne .delaytop
|
||||||
|
pop {lr}
|
||||||
|
.delayreturn:
|
||||||
|
bx lr
|
279
kernel/qdivrem.c
Normal file
279
kernel/qdivrem.c
Normal file
|
@ -0,0 +1,279 @@
|
||||||
|
/*-
|
||||||
|
* Copyright (c) 1992, 1993
|
||||||
|
* The Regents of the University of California. All rights reserved.
|
||||||
|
*
|
||||||
|
* This software was developed by the Computer Systems Engineering group
|
||||||
|
* at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
|
||||||
|
* contributed to Berkeley.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 4. Neither the name of the University nor the names of its contributors
|
||||||
|
* may be used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
/* Derived from FreeBSD libkern qdivrem.c, munged by Erbo to COMROGUE standards */
|
||||||
|
#include <comrogue/types.h>
|
||||||
|
#include <comrogue/internals/seg.h>
|
||||||
|
#include "quad.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Multiprecision divide. This algorithm is from Knuth vol. 2 (2nd ed),
|
||||||
|
* section 4.3.1, pp. 257--259.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define B (1 << HALF_BITS) /* digit base */
|
||||||
|
|
||||||
|
/* Combine two `digits' to make a single two-digit number. */
|
||||||
|
#define COMBINE(a, b) (((UINT32)(a) << HALF_BITS) | (b))
|
||||||
|
|
||||||
|
/* select a type for digits in base B: use unsigned short if they fit */
|
||||||
|
typedef UINT16 DIGIT;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Shift p[0]..p[len] left `sh' bits, ignoring any bits that
|
||||||
|
* `fall out' the left (there never will be any such anyway).
|
||||||
|
* We may assume len >= 0. NOTE THAT THIS WRITES len+1 DIGITS.
|
||||||
|
*/
|
||||||
|
SEG_LIB_CODE static void __shl(register DIGIT *p, register INT32 len, register INT32 sh)
|
||||||
|
{
|
||||||
|
register INT32 i;
|
||||||
|
|
||||||
|
for (i = 0; i < len; i++)
|
||||||
|
p[i] = LHALF(p[i] << sh) | (p[i + 1] >> (HALF_BITS - sh));
|
||||||
|
p[i] = LHALF(p[i] << sh);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* __qdivrem(u, v, rem) returns u/v and, optionally, sets *rem to u%v.
|
||||||
|
*
|
||||||
|
* We do this in base 2^HALF_BITS, so that all intermediate products
|
||||||
|
* fit within u_long. As a consequence, the maximum length dividend and
|
||||||
|
* divisor are 4 `digits' in this base (they are shorter if they have
|
||||||
|
* leading zeros).
|
||||||
|
*/
|
||||||
|
SEG_LIB_CODE UINT64 __qdivrem(UINT64 uq, UINT64 vq, PUINT64 pRem)
|
||||||
|
{
|
||||||
|
UU tmp;
|
||||||
|
DIGIT *u, *v, *q;
|
||||||
|
register DIGIT v1, v2;
|
||||||
|
UINT32 qhat, rhat, t;
|
||||||
|
INT32 m, n, d, j, i;
|
||||||
|
DIGIT uspace[5], vspace[5], qspace[5];
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Take care of special cases: divide by zero, and u < v.
|
||||||
|
*/
|
||||||
|
if (vq == 0)
|
||||||
|
{ /* divide by zero. */
|
||||||
|
SEG_LIB_RODATA static volatile const unsigned int zero = 0;
|
||||||
|
|
||||||
|
tmp.ul[H] = tmp.ul[L] = 1 / zero;
|
||||||
|
if (pRem)
|
||||||
|
*pRem = uq;
|
||||||
|
return tmp.q;
|
||||||
|
}
|
||||||
|
if (uq < vq)
|
||||||
|
{
|
||||||
|
if (pRem)
|
||||||
|
*pRem = uq;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
u = uspace;
|
||||||
|
v = vspace;
|
||||||
|
q = qspace;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Break dividend and divisor into digits in base B, then
|
||||||
|
* count leading zeros to determine m and n. When done, we
|
||||||
|
* will have:
|
||||||
|
* u = (u[1]u[2]...u[m+n]) sub B
|
||||||
|
* v = (v[1]v[2]...v[n]) sub B
|
||||||
|
* v[1] != 0
|
||||||
|
* 1 < n <= 4 (if n = 1, we use a different division algorithm)
|
||||||
|
* m >= 0 (otherwise u < v, which we already checked)
|
||||||
|
* m + n = 4
|
||||||
|
* and thus
|
||||||
|
* m = 4 - n <= 2
|
||||||
|
*/
|
||||||
|
tmp.uq = uq;
|
||||||
|
u[0] = 0;
|
||||||
|
u[1] = HHALF(tmp.ul[H]);
|
||||||
|
u[2] = LHALF(tmp.ul[H]);
|
||||||
|
u[3] = HHALF(tmp.ul[L]);
|
||||||
|
u[4] = LHALF(tmp.ul[L]);
|
||||||
|
tmp.uq = vq;
|
||||||
|
v[1] = HHALF(tmp.ul[H]);
|
||||||
|
v[2] = LHALF(tmp.ul[H]);
|
||||||
|
v[3] = HHALF(tmp.ul[L]);
|
||||||
|
v[4] = LHALF(tmp.ul[L]);
|
||||||
|
for (n = 4; v[1] == 0; v++)
|
||||||
|
{
|
||||||
|
if (--n == 1)
|
||||||
|
{
|
||||||
|
UINT32 rbj; /* r*B+u[j] (not root boy jim) */
|
||||||
|
DIGIT q1, q2, q3, q4;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Change of plan, per exercise 16.
|
||||||
|
* r = 0;
|
||||||
|
* for j = 1..4:
|
||||||
|
* q[j] = floor((r*B + u[j]) / v),
|
||||||
|
* r = (r*B + u[j]) % v;
|
||||||
|
* We unroll this completely here.
|
||||||
|
*/
|
||||||
|
t = v[2]; /* nonzero, by definition */
|
||||||
|
q1 = u[1] / t;
|
||||||
|
rbj = COMBINE(u[1] % t, u[2]);
|
||||||
|
q2 = rbj / t;
|
||||||
|
rbj = COMBINE(rbj % t, u[3]);
|
||||||
|
q3 = rbj / t;
|
||||||
|
rbj = COMBINE(rbj % t, u[4]);
|
||||||
|
q4 = rbj / t;
|
||||||
|
if (pRem)
|
||||||
|
*pRem = rbj % t;
|
||||||
|
tmp.ul[H] = COMBINE(q1, q2);
|
||||||
|
tmp.ul[L] = COMBINE(q3, q4);
|
||||||
|
return tmp.q;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* By adjusting q once we determine m, we can guarantee that
|
||||||
|
* there is a complete four-digit quotient at &qspace[1] when
|
||||||
|
* we finally stop.
|
||||||
|
*/
|
||||||
|
for (m = 4 - n; u[1] == 0; u++)
|
||||||
|
m--;
|
||||||
|
for (i = 4 - m; --i >= 0;)
|
||||||
|
q[i] = 0;
|
||||||
|
q += 4 - m;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Here we run Program D, translated from MIX to C and acquiring
|
||||||
|
* a few minor changes.
|
||||||
|
*
|
||||||
|
* D1: choose multiplier 1 << d to ensure v[1] >= B/2.
|
||||||
|
*/
|
||||||
|
d = 0;
|
||||||
|
for (t = v[1]; t < B / 2; t <<= 1)
|
||||||
|
d++;
|
||||||
|
if (d > 0)
|
||||||
|
{
|
||||||
|
__shl(u, m + n, d); /* u <<= d */
|
||||||
|
__shl(v + 1, n - 1, d); /* v <<= d */
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* D2: j = 0.
|
||||||
|
*/
|
||||||
|
j = 0;
|
||||||
|
v1 = v[1]; /* for D3 -- note that v[1..n] are constant */
|
||||||
|
v2 = v[2]; /* for D3 */
|
||||||
|
do
|
||||||
|
{
|
||||||
|
register DIGIT uj0, uj1, uj2;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* D3: Calculate qhat (\^q, in TeX notation).
|
||||||
|
* Let qhat = min((u[j]*B + u[j+1])/v[1], B-1), and
|
||||||
|
* let rhat = (u[j]*B + u[j+1]) mod v[1].
|
||||||
|
* While rhat < B and v[2]*qhat > rhat*B+u[j+2],
|
||||||
|
* decrement qhat and increase rhat correspondingly.
|
||||||
|
* Note that if rhat >= B, v[2]*qhat < rhat*B.
|
||||||
|
*/
|
||||||
|
uj0 = u[j + 0]; /* for D3 only -- note that u[j+...] change */
|
||||||
|
uj1 = u[j + 1]; /* for D3 only */
|
||||||
|
uj2 = u[j + 2]; /* for D3 only */
|
||||||
|
if (uj0 == v1)
|
||||||
|
{
|
||||||
|
qhat = B;
|
||||||
|
rhat = uj1;
|
||||||
|
goto qhat_too_big;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
UINT32 nn = COMBINE(uj0, uj1);
|
||||||
|
qhat = nn / v1;
|
||||||
|
rhat = nn % v1;
|
||||||
|
}
|
||||||
|
while (v2 * qhat > COMBINE(rhat, uj2))
|
||||||
|
{
|
||||||
|
qhat_too_big:
|
||||||
|
qhat--;
|
||||||
|
if ((rhat += v1) >= B)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* D4: Multiply and subtract.
|
||||||
|
* The variable `t' holds any borrows across the loop.
|
||||||
|
* We split this up so that we do not require v[0] = 0,
|
||||||
|
* and to eliminate a final special case.
|
||||||
|
*/
|
||||||
|
for (t = 0, i = n; i > 0; i--)
|
||||||
|
{
|
||||||
|
t = u[i + j] - v[i] * qhat - t;
|
||||||
|
u[i + j] = LHALF(t);
|
||||||
|
t = (B - HHALF(t)) & (B - 1);
|
||||||
|
}
|
||||||
|
t = u[j] - t;
|
||||||
|
u[j] = LHALF(t);
|
||||||
|
/*
|
||||||
|
* D5: test remainder.
|
||||||
|
* There is a borrow if and only if HHALF(t) is nonzero;
|
||||||
|
* in that (rare) case, qhat was too large (by exactly 1).
|
||||||
|
* Fix it by adding v[1..n] to u[j..j+n].
|
||||||
|
*/
|
||||||
|
if (HHALF(t))
|
||||||
|
{
|
||||||
|
qhat--;
|
||||||
|
for (t = 0, i = n; i > 0; i--)
|
||||||
|
{ /* D6: add back. */
|
||||||
|
t += u[i + j] + v[i];
|
||||||
|
u[i + j] = LHALF(t);
|
||||||
|
t = HHALF(t);
|
||||||
|
}
|
||||||
|
u[j] = LHALF(u[j] + t);
|
||||||
|
}
|
||||||
|
q[j] = qhat;
|
||||||
|
} while (++j <= m); /* D7: loop on j. */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If caller wants the remainder, we have to calculate it as
|
||||||
|
* u[m..m+n] >> d (this is at most n digits and thus fits in
|
||||||
|
* u[m+1..m+n], but we may need more source digits).
|
||||||
|
*/
|
||||||
|
if (pRem)
|
||||||
|
{
|
||||||
|
if (d)
|
||||||
|
{
|
||||||
|
for (i = m + n; i > m; --i)
|
||||||
|
u[i] = (u[i] >> d) | LHALF(u[i - 1] << (HALF_BITS - d));
|
||||||
|
u[i] = 0;
|
||||||
|
}
|
||||||
|
tmp.ul[H] = COMBINE(uspace[1], uspace[2]);
|
||||||
|
tmp.ul[L] = COMBINE(uspace[3], uspace[4]);
|
||||||
|
*pRem = tmp.q;
|
||||||
|
}
|
||||||
|
|
||||||
|
tmp.ul[H] = COMBINE(qspace[1], qspace[2]);
|
||||||
|
tmp.ul[L] = COMBINE(qspace[3], qspace[4]);
|
||||||
|
return tmp.q;
|
||||||
|
}
|
71
kernel/quad.h
Normal file
71
kernel/quad.h
Normal file
|
@ -0,0 +1,71 @@
|
||||||
|
/*-
|
||||||
|
* Copyright (c) 1992, 1993
|
||||||
|
* The Regents of the University of California. All rights reserved.
|
||||||
|
*
|
||||||
|
* This software was developed by the Computer Systems Engineering group
|
||||||
|
* at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
|
||||||
|
* contributed to Berkeley.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 4. Neither the name of the University nor the names of its contributors
|
||||||
|
* may be used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* @(#)quad.h 8.1 (Berkeley) 6/4/93
|
||||||
|
* $FreeBSD$
|
||||||
|
*/
|
||||||
|
/* Derived from FreeBDS libkern quad.h, munged by Erbo to COMROGUE standards */
|
||||||
|
#ifndef QUAD_H_INCLUDED
|
||||||
|
#define QUAD_H_INCLUDED
|
||||||
|
|
||||||
|
#include <comrogue/types.h>
|
||||||
|
|
||||||
|
typedef union tagUU {
|
||||||
|
INT64 q; /* signed quad */
|
||||||
|
UINT64 uq; /* unsigned quad */
|
||||||
|
INT32 sl[2]; /* two signed longs */
|
||||||
|
UINT32 ul[2]; /* two unsigned longs */
|
||||||
|
} UU;
|
||||||
|
|
||||||
|
/* Low word/high word definitions. */
|
||||||
|
#define L 0
|
||||||
|
#define H 1
|
||||||
|
|
||||||
|
/* Number of bits in a halfword. */
|
||||||
|
#define HALF_BITS (INT32_BITS / 2)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Extract high and low shortwords from longword, and move low shortword of
|
||||||
|
* longword to upper half of long, i.e., produce the upper longword of
|
||||||
|
* ((quad_t)(x) << (number_of_bits_in_long/2)). (`x' must actually be u_long.)
|
||||||
|
*
|
||||||
|
* These are used in the multiply code, to split a longword into upper
|
||||||
|
* and lower halves, and to reassemble a product as a quad_t, shifted left
|
||||||
|
* (sizeof(long)*CHAR_BIT/2).
|
||||||
|
*/
|
||||||
|
#define HHALF(x) ((x) >> HALF_BITS)
|
||||||
|
#define LHALF(x) ((x) & ((1 << HALF_BITS) - 1))
|
||||||
|
#define LHUP(x) ((x) << HALF_BITS)
|
||||||
|
|
||||||
|
extern UINT64 __qdivrem(UINT64 u, UINT64 v, PUINT64 pRem);
|
||||||
|
|
||||||
|
#endif /* QUAD_H_INCLUDED */
|
117
kernel/start.S
Normal file
117
kernel/start.S
Normal file
|
@ -0,0 +1,117 @@
|
||||||
|
/*
|
||||||
|
* This file is part of the COMROGUE Operating System for Raspberry Pi
|
||||||
|
*
|
||||||
|
* Copyright (c) 2013, Eric J. Bowersox / Erbosoft Enterprises
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This program is free for commercial and non-commercial use as long as the following conditions are
|
||||||
|
* adhered to.
|
||||||
|
*
|
||||||
|
* Copyright in this file remains Eric J. Bowersox and/or Erbosoft, and as such any copyright notices
|
||||||
|
* in the code are not to be removed.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification, are permitted
|
||||||
|
* provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* * Redistributions of source code must retain the above copyright notice, this list of conditions and
|
||||||
|
* the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
|
||||||
|
* the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
|
||||||
|
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||||
|
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||||
|
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* "Raspberry Pi" is a trademark of the Raspberry Pi Foundation.
|
||||||
|
*/
|
||||||
|
#include <comrogue/internals/layout.h>
|
||||||
|
#include <comrogue/internals/sctlr.h>
|
||||||
|
|
||||||
|
.section ".initHEAD.text"
|
||||||
|
|
||||||
|
.globl COMROGUEStart
|
||||||
|
|
||||||
|
/* entry: r0 = physical (low-memory) address of STARTUP_INFO1 structure */
|
||||||
|
COMROGUEStart:
|
||||||
|
/* initialize the stack pointer */
|
||||||
|
ldr sp, =.initstack
|
||||||
|
|
||||||
|
/* clear init bss */
|
||||||
|
ldr r4, =vmaInitBss
|
||||||
|
ldr r5, =vmaFirstFree
|
||||||
|
mov r6, #0
|
||||||
|
mov r7, #0
|
||||||
|
mov r8, #0
|
||||||
|
mov r9, #0
|
||||||
|
bl .erase
|
||||||
|
|
||||||
|
/* clear resident bss */
|
||||||
|
ldr r4, =vmaKernelBss
|
||||||
|
ldr r5, =vmaInitCode
|
||||||
|
bl .erase
|
||||||
|
|
||||||
|
/* initialize trace */
|
||||||
|
push {r0}
|
||||||
|
bl TrInit
|
||||||
|
#if 0
|
||||||
|
ldr r0, =.msg0
|
||||||
|
bl TrWriteString8
|
||||||
|
#endif
|
||||||
|
pop {r0}
|
||||||
|
|
||||||
|
/* copy startup info to our local buffer */
|
||||||
|
mov r1, r0
|
||||||
|
ldr r0, =kiStartupInfo
|
||||||
|
mov r11, r0 /* save for later */
|
||||||
|
ldr r2, [r1] /* get number of bytes to copy */
|
||||||
|
ldr ip, =StrCopyMem /* this is needed to branch to a library function */
|
||||||
|
ldr lr, =.postCopy
|
||||||
|
mov pc, ip
|
||||||
|
|
||||||
|
.postCopy:
|
||||||
|
#if 0
|
||||||
|
ldr r0, =.msg1
|
||||||
|
bl TrWriteString8
|
||||||
|
#endif
|
||||||
|
|
||||||
|
mcr p15, 0, r6, c7, c7, 0 /* clear caches */
|
||||||
|
mcr p15, 0, r6, c8, c7, 0 /* clear TLB */
|
||||||
|
mrc p15, 0, r0, c1, c0, 0
|
||||||
|
orr r0, r0, # SCTLR_I /* activate instruction cache */
|
||||||
|
orr r0, r0, # SCTLR_C /* activate data cache */
|
||||||
|
mcr p15, 0, r0, c1, c0, 0
|
||||||
|
|
||||||
|
/* transfer to C code to continue initialization */
|
||||||
|
ldr ip, =KiSystemStartup
|
||||||
|
ldr lr, =.hang
|
||||||
|
mov pc, ip /* transfer to C code */
|
||||||
|
.hang:
|
||||||
|
wfe /* if KiSystemStartup returns, just hang */
|
||||||
|
b .hang
|
||||||
|
|
||||||
|
/* Simple erase routine. Start and end addresses in r4 and r5. r6-r9 assumed to be 0. */
|
||||||
|
/* Do not touch r0-r2. */
|
||||||
|
.erase:
|
||||||
|
cmp r4, r5 /* are we done? */
|
||||||
|
movhs pc, lr /* yes, return */
|
||||||
|
stm r4!, {r6-r9} /* stomp 16 bytes */
|
||||||
|
b .erase
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
.balign 4
|
||||||
|
.msg0:
|
||||||
|
.asciz "got here 2\n"
|
||||||
|
.balign 4
|
||||||
|
.msg1:
|
||||||
|
.asciz "got here 3\n"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
.section ".init.bss"
|
||||||
|
.balign 4
|
||||||
|
.space 4096
|
||||||
|
.initstack:
|
423
kernel/str.c
Normal file
423
kernel/str.c
Normal file
|
@ -0,0 +1,423 @@
|
||||||
|
/*
|
||||||
|
* This file is part of the COMROGUE Operating System for Raspberry Pi
|
||||||
|
*
|
||||||
|
* Copyright (c) 2013, Eric J. Bowersox / Erbosoft Enterprises
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This program is free for commercial and non-commercial use as long as the following conditions are
|
||||||
|
* adhered to.
|
||||||
|
*
|
||||||
|
* Copyright in this file remains Eric J. Bowersox and/or Erbosoft, and as such any copyright notices
|
||||||
|
* in the code are not to be removed.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification, are permitted
|
||||||
|
* provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* * Redistributions of source code must retain the above copyright notice, this list of conditions and
|
||||||
|
* the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
|
||||||
|
* the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
|
||||||
|
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||||
|
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||||
|
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* "Raspberry Pi" is a trademark of the Raspberry Pi Foundation.
|
||||||
|
*/
|
||||||
|
#include <comrogue/types.h>
|
||||||
|
#include <comrogue/scode.h>
|
||||||
|
#include <comrogue/intlib.h>
|
||||||
|
#include <comrogue/str.h>
|
||||||
|
#include <comrogue/internals/seg.h>
|
||||||
|
|
||||||
|
/*-------------------------
|
||||||
|
* Basic string operations
|
||||||
|
*-------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Returns whether or not the character is a digit (0-9).
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* - ch = Character to be tested.
|
||||||
|
*
|
||||||
|
* Returns:
|
||||||
|
* TRUE if the character is a digit, FALSE otherwise.
|
||||||
|
*/
|
||||||
|
SEG_LIB_CODE BOOL StrIsDigit8(CHAR ch)
|
||||||
|
{
|
||||||
|
/* TODO: replace with something nicer later */
|
||||||
|
return MAKEBOOL((ch >= '0') && (ch <= '9'));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Returns the length of a null-terminated string.
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* - psz = The string to get the length of.
|
||||||
|
*
|
||||||
|
* Returns:
|
||||||
|
* The length of the string in characters.
|
||||||
|
*/
|
||||||
|
SEG_LIB_CODE INT32 StrLength8(PCSTR psz)
|
||||||
|
{
|
||||||
|
register PCSTR p = psz;
|
||||||
|
while (*p)
|
||||||
|
p++;
|
||||||
|
return (INT32)(p - psz);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Locates a character within a null-terminated string.
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* - psz = String to search through for character.
|
||||||
|
* - ch = Character to look for.
|
||||||
|
*
|
||||||
|
* Returns:
|
||||||
|
* NULL if character was not found, otherwise pointer to character within string.
|
||||||
|
*/
|
||||||
|
SEG_LIB_CODE PCHAR StrChar8(PCSTR psz, INT32 ch)
|
||||||
|
{
|
||||||
|
const CHAR mych = ch;
|
||||||
|
for (; *psz; psz++)
|
||||||
|
if (*psz == mych)
|
||||||
|
return (PCHAR)psz;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-------------------------------
|
||||||
|
* Numeric-to-string conversions
|
||||||
|
*-------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Formats an unsigned numeric value into a buffer. This function formats the value into the END of the
|
||||||
|
* buffer and returns a pointer to the first character of the number. Note that the string-converted number
|
||||||
|
* is NOT null-terminated!
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* - value = The value to be converted.
|
||||||
|
* - pchBuf = Pointer to the buffer in which to store the converted value.
|
||||||
|
* - nBytes = Number of characters in the buffer.
|
||||||
|
* - nBase = The numeric base to use to output the number. Valid values are in the interval [2,36].
|
||||||
|
* - fUppercase = TRUE to use upper-case letters as digits in output, FALSE to use lower-case letters.
|
||||||
|
*
|
||||||
|
* Returns:
|
||||||
|
* A pointer to the first digit of the converted value, which will be somewhere in the interval
|
||||||
|
* [pchBuf, pchBuf + nBytes).
|
||||||
|
*/
|
||||||
|
SEG_LIB_CODE static PCHAR convert_number_engine8(UINT64 value, PCHAR pchBuf, INT32 nBytes, INT32 nBase,
|
||||||
|
BOOL fUppercase)
|
||||||
|
{
|
||||||
|
static DECLARE_LIB_STRING8_CONST(szDigitsUppercase, "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ");
|
||||||
|
static DECLARE_LIB_STRING8_CONST(szDigitsLowercase, "0123456789abcdefghijklmnopqrstuvwxyz");
|
||||||
|
PCSTR pszDigits = (fUppercase ? szDigitsUppercase : szDigitsLowercase); /* digit set to use */
|
||||||
|
PCHAR p = pchBuf + nBytes; /* output pointer */
|
||||||
|
INT64 accumulator; /* accumulator of quotients */
|
||||||
|
LDIV ldiv; /* buffer for division */
|
||||||
|
|
||||||
|
/* do initial division to get rid of high-order bit & handle 0 */
|
||||||
|
*--p = pszDigits[value % nBase];
|
||||||
|
accumulator = (INT64)(value / nBase);
|
||||||
|
|
||||||
|
while ((p > pchBuf) && (accumulator > 0))
|
||||||
|
{ /* output digits */
|
||||||
|
IntLDiv(&ldiv, accumulator, nBase);
|
||||||
|
*--p = pszDigits[ldiv.rem];
|
||||||
|
accumulator = ldiv.quot;
|
||||||
|
}
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------
|
||||||
|
* StrFormatV8 and its support definitions
|
||||||
|
*-----------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Flag values for conversion characters */
|
||||||
|
#define FLAG_LEFTJUST 0x01 /* left-justify output field */
|
||||||
|
#define FLAG_PLUSSIGN 0x02 /* use a '+' for the sign if >= 0 */
|
||||||
|
#define FLAG_SPACESIGN 0x04 /* use a space for the sign if >= 0 */
|
||||||
|
#define FLAG_ALTMODE 0x08 /* alternate conversion mode */
|
||||||
|
#define FLAG_ZEROPAD 0x10 /* zero-pad to width */
|
||||||
|
|
||||||
|
/* Macro that calls the output function and either updates total output or exits */
|
||||||
|
#define do_output(pBuf, nChr) \
|
||||||
|
do { if ((nChr) > 0) { if (SUCCEEDED((*pfnFormat)(&pArg, (pBuf), (nChr)))) nTotalOutput += (nChr); \
|
||||||
|
else { errorFlag = SEVERITY_ERROR; goto error; } } } while (0)
|
||||||
|
|
||||||
|
/* Strings used for padding */
|
||||||
|
static DECLARE_LIB_STRING8_CONST(szPadSpace, " ");
|
||||||
|
static DECLARE_LIB_STRING8_CONST(szPadZero, "0000000000000000000000000000000000000000000000000000000000");
|
||||||
|
|
||||||
|
#define PAD_SIZE (sizeof(szPadSpace) - 1) /* number of characters available in pad string */
|
||||||
|
|
||||||
|
/* Macro that outputs characters for padding */
|
||||||
|
#define do_pad_output(szPad, nChr) \
|
||||||
|
do { int n, nt = (nChr); while (nt > 0) { n = intMin(nt, PAD_SIZE); do_output(szPad, n); nt -= n; } } while (0)
|
||||||
|
|
||||||
|
#define MAX_VAL 509 /* maximum field value for conversion */
|
||||||
|
#define BUFSIZE 64 /* buffer size on stack for conversion */
|
||||||
|
#define NUM_CONVERT_BYTES 32 /* maximum number of bytes for converting a numeric value */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Format a series of arguments like "printf," calling a function to perform the actual character output.
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* - pfnFormat = Pointer to the format function
|
||||||
|
* - pArg = Pointer argument passed to the format function, which may modify it
|
||||||
|
* - pszFormat = Format string, like a printf format string.
|
||||||
|
* - pargs = Pointer to varargs-style function arguments.
|
||||||
|
*
|
||||||
|
* Returns:
|
||||||
|
* A HRESULT as follows: Severity indicates whether the output function failed or succeeded, facility is always
|
||||||
|
* FACILITY_STRFORMAT, code indicates the number of characters output.
|
||||||
|
*
|
||||||
|
* Notes:
|
||||||
|
* Floating-point conversion formats are not supported at this time.
|
||||||
|
*/
|
||||||
|
SEG_LIB_CODE HRESULT StrFormatV8(PFNFORMAT8 pfnFormat, PVOID pArg, PCSTR pszFormat, va_list pargs)
|
||||||
|
{
|
||||||
|
static DECLARE_LIB_STRING8_CONST(szFlagChars, "0+- #"); /* flag characters and values */
|
||||||
|
static const UINT32 SEG_LIB_RODATA auiFlagValues[] =
|
||||||
|
{ FLAG_ZEROPAD, FLAG_LEFTJUST, FLAG_PLUSSIGN, FLAG_SPACESIGN, FLAG_ALTMODE, 0 };
|
||||||
|
static DECLARE_LIB_STRING8_CONST(szConversionChars, "hl"); /* conversion characters */
|
||||||
|
PCSTR p; /* pointer used to walk the format string */
|
||||||
|
PCHAR pFlag; /* pointer to flag character/temp buffer pointer */
|
||||||
|
PCHAR pchOutput; /* pointer to characters actually output */
|
||||||
|
INT32 nchOutput; /* number of characters output */
|
||||||
|
PCHAR pchPrefix; /* pointer to prefix characters */
|
||||||
|
INT32 nchPrefix; /* number of prefix characters */
|
||||||
|
INT32 nchZeroPrefix; /* number of zeroes to write as a prefix */
|
||||||
|
INT32 nTotalOutput = 0; /* total number of characters output */
|
||||||
|
UINT32 errorFlag = SEVERITY_SUCCESS; /* error flag to return */
|
||||||
|
UINT32 flags; /* conversion flags seen */
|
||||||
|
INT32 ncWidth; /* width for field */
|
||||||
|
INT32 ncPrecision; /* precision for field */
|
||||||
|
INT32 nBase; /* numeric base for field */
|
||||||
|
INT64 input; /* input integer value */
|
||||||
|
CHAR chConvert; /* conversion character for field */
|
||||||
|
CHAR achBuffer[BUFSIZE]; /* buffer into which output is formatted */
|
||||||
|
|
||||||
|
while (*pszFormat)
|
||||||
|
{
|
||||||
|
/* locate all plain characters up to next % or end of string and output them */
|
||||||
|
p = pszFormat;
|
||||||
|
while (*p && (*p != '%'))
|
||||||
|
p++;
|
||||||
|
do_output(pszFormat, p - pszFormat);
|
||||||
|
|
||||||
|
if (*p == '%')
|
||||||
|
{
|
||||||
|
flags = 0; /* convert flags first */
|
||||||
|
for (p++; (pFlag = StrChar8(szFlagChars, *p)) != NULL; p++)
|
||||||
|
flags |= auiFlagValues[pFlag - szFlagChars];
|
||||||
|
|
||||||
|
ncWidth = 0; /* now convert width */
|
||||||
|
if (*p == '*')
|
||||||
|
{
|
||||||
|
ncWidth = va_arg(pargs, INT32); /* specified by arg */
|
||||||
|
p++;
|
||||||
|
if (ncWidth < 0)
|
||||||
|
{
|
||||||
|
flags |= FLAG_LEFTJUST; /* negative width is taken as use of - flag */
|
||||||
|
ncWidth = -ncWidth;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
while (StrIsDigit8(*p))
|
||||||
|
ncWidth = ncWidth * 10 + (*p++ - '0');
|
||||||
|
}
|
||||||
|
if (ncWidth > MAX_VAL)
|
||||||
|
ncWidth = MAX_VAL;
|
||||||
|
|
||||||
|
ncPrecision = -1; /* now convert precision */
|
||||||
|
if (*p == '.')
|
||||||
|
{
|
||||||
|
p++;
|
||||||
|
if (*p == '*')
|
||||||
|
{
|
||||||
|
ncPrecision = va_arg(pargs, INT32); /* specified by arg */
|
||||||
|
p++;
|
||||||
|
/* N.B. ncPrecision < 0 = "omitted precision" */
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ncPrecision = 0;
|
||||||
|
while (StrIsDigit8(*p))
|
||||||
|
ncPrecision = ncPrecision * 10 + (*p++ - '0');
|
||||||
|
}
|
||||||
|
if (ncPrecision > MAX_VAL)
|
||||||
|
ncPrecision = MAX_VAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
chConvert = StrChar8(szConversionChars, *p) ? *p++ : '\0'; /* get conversion character */
|
||||||
|
|
||||||
|
/* based on field character, convert the field */
|
||||||
|
pchOutput = achBuffer;
|
||||||
|
nchOutput = 0;
|
||||||
|
pchPrefix = NULL;
|
||||||
|
nchPrefix = 0;
|
||||||
|
nchZeroPrefix = 0;
|
||||||
|
switch (*p)
|
||||||
|
{
|
||||||
|
case 'c': /* output a character */
|
||||||
|
achBuffer[nchOutput++] = (CHAR)va_arg(pargs, INT32);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'd':
|
||||||
|
case 'i': /* output a decimal number */
|
||||||
|
if (ncPrecision < 0)
|
||||||
|
ncPrecision = 1; /* default precision is 1 */
|
||||||
|
if (chConvert == 'h')
|
||||||
|
input = va_arg(pargs, INT32);
|
||||||
|
else if (chConvert == '\0')
|
||||||
|
input = va_arg(pargs, INT32);
|
||||||
|
else
|
||||||
|
input = va_arg(pargs, INT64);
|
||||||
|
if ((input == 0) && (ncPrecision == 0))
|
||||||
|
break; /* no output */
|
||||||
|
|
||||||
|
if (input < 0)
|
||||||
|
{
|
||||||
|
achBuffer[nchPrefix++] = '-'; /* minus sign */
|
||||||
|
input = -input;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* plus or space for sign if flags dictate */
|
||||||
|
if (flags & FLAG_PLUSSIGN)
|
||||||
|
achBuffer[nchPrefix++] = '+';
|
||||||
|
else if (flags & FLAG_SPACESIGN)
|
||||||
|
achBuffer[nchPrefix++] = ' ';
|
||||||
|
}
|
||||||
|
if (nchPrefix > 0)
|
||||||
|
{
|
||||||
|
pchPrefix = achBuffer; /* adjust output pointer and set prefix */
|
||||||
|
pchOutput = achBuffer + nchPrefix;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* clamp input value and run it through number conversion engine */
|
||||||
|
if (chConvert == 'h')
|
||||||
|
input &= UINT16_MAX;
|
||||||
|
else if (chConvert == '\0')
|
||||||
|
input &= UINT32_MAX;
|
||||||
|
pFlag = pchOutput;
|
||||||
|
pchOutput = convert_number_engine8((UINT64)input, pFlag, NUM_CONVERT_BYTES, 10, FALSE);
|
||||||
|
nchOutput = (pFlag + NUM_CONVERT_BYTES) - pchOutput;
|
||||||
|
|
||||||
|
/* calculate zero prefix based on precision */
|
||||||
|
if ((flags & (FLAG_ZEROPAD|FLAG_LEFTJUST)) == FLAG_ZEROPAD)
|
||||||
|
nchZeroPrefix = intMax(0, ncWidth - (nchPrefix + nchOutput));
|
||||||
|
else if (ncPrecision > 0)
|
||||||
|
nchZeroPrefix = intMax(0, ncPrecision - nchOutput);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'o':
|
||||||
|
case 'u':
|
||||||
|
case 'x':
|
||||||
|
case 'X': /* output an unsigned number */
|
||||||
|
if (ncPrecision < 0)
|
||||||
|
ncPrecision = 1; /* defualt precision is 1 */
|
||||||
|
if (chConvert == 'h')
|
||||||
|
input = va_arg(pargs, UINT32);
|
||||||
|
else if (chConvert == '\0')
|
||||||
|
input = va_arg(pargs, UINT32);
|
||||||
|
else
|
||||||
|
input = (INT64)va_arg(pargs, UINT64);
|
||||||
|
if ((input == 0) && (ncPrecision == 0))
|
||||||
|
break; /* no output */
|
||||||
|
|
||||||
|
/* select numeric base of output */
|
||||||
|
if (*p == 'o')
|
||||||
|
nBase = 8;
|
||||||
|
else if (*p == 'u')
|
||||||
|
nBase = 10;
|
||||||
|
else
|
||||||
|
nBase = 16;
|
||||||
|
|
||||||
|
if (flags & FLAG_ALTMODE)
|
||||||
|
{
|
||||||
|
if (*p == 'o')
|
||||||
|
{ /* forced octal notation */
|
||||||
|
achBuffer[nchPrefix++] = '0';
|
||||||
|
ncPrecision--;
|
||||||
|
}
|
||||||
|
else if (*p != 'u')
|
||||||
|
{ /* forced hexadecimal notation */
|
||||||
|
achBuffer[nchPrefix++] = '0';
|
||||||
|
achBuffer[nchPrefix++] = *p;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (nchPrefix > 0)
|
||||||
|
{
|
||||||
|
pchPrefix = achBuffer; /* adjust output pointer and set prefix */
|
||||||
|
pchOutput = achBuffer + nchPrefix;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* clamp input value and run it through number conversion engine */
|
||||||
|
if (chConvert == 'h')
|
||||||
|
input &= UINT16_MAX;
|
||||||
|
else if (chConvert == '\0')
|
||||||
|
input &= UINT32_MAX;
|
||||||
|
pFlag = pchOutput;
|
||||||
|
pchOutput = convert_number_engine8((UINT64)input, pFlag, NUM_CONVERT_BYTES, nBase, MAKEBOOL(*p == 'X'));
|
||||||
|
nchOutput = (pFlag + NUM_CONVERT_BYTES) - pchOutput;
|
||||||
|
|
||||||
|
/* calculate zero prefix based on precision */
|
||||||
|
if ((flags & (FLAG_ZEROPAD|FLAG_LEFTJUST)) == FLAG_ZEROPAD)
|
||||||
|
nchZeroPrefix = intMax(0, ncWidth - (nchPrefix + nchOutput));
|
||||||
|
else if (ncPrecision > 0)
|
||||||
|
nchZeroPrefix = intMax(0, ncPrecision - nchOutput);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'p': /* output a pointer value - treated as unsigned hex with precision of 8 */
|
||||||
|
input = (INT_PTR)va_arg(pargs, PVOID);
|
||||||
|
input &= UINT_PTR_MAX;
|
||||||
|
pFlag = pchOutput;
|
||||||
|
pchOutput = convert_number_engine8((UINT64)input, pFlag, NUM_CONVERT_BYTES, 16, FALSE);
|
||||||
|
nchOutput = (pFlag + NUM_CONVERT_BYTES) - pchOutput;
|
||||||
|
nchZeroPrefix = intMax(0, (sizeof(UINT_PTR) / sizeof(CHAR) * 2) - nchOutput);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 's': /* output a string */
|
||||||
|
pchOutput = (PCHAR)va_arg(pargs, PCSTR);
|
||||||
|
nchOutput = StrLength8(pchOutput);
|
||||||
|
if ((ncPrecision >= 0) && (ncPrecision < nchOutput))
|
||||||
|
nchOutput = ncPrecision;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'n': /* output nothing, just store number of characters output so far */
|
||||||
|
*(va_arg(pargs, PINT32)) = nTotalOutput;
|
||||||
|
goto no_output;
|
||||||
|
|
||||||
|
case '%': /* output a single % sign */
|
||||||
|
default: /* unrecognized format character, output it and continue */
|
||||||
|
achBuffer[nchOutput++] = *p;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
ncWidth -= (nchPrefix + nchZeroPrefix + nchOutput);
|
||||||
|
if (!(flags & FLAG_LEFTJUST))
|
||||||
|
do_pad_output(szPadSpace, ncWidth);
|
||||||
|
do_output(pchPrefix, nchPrefix);
|
||||||
|
do_pad_output(szPadZero, nchZeroPrefix);
|
||||||
|
do_output(pchOutput, nchOutput);
|
||||||
|
if (flags & FLAG_LEFTJUST)
|
||||||
|
do_pad_output(szPadSpace, ncWidth);
|
||||||
|
|
||||||
|
no_output:
|
||||||
|
p++;
|
||||||
|
}
|
||||||
|
pszFormat = p;
|
||||||
|
}
|
||||||
|
error:
|
||||||
|
return MAKE_SCODE(errorFlag, FACILITY_STRFORMAT, nTotalOutput);
|
||||||
|
}
|
273
kernel/strcopymem.S
Normal file
273
kernel/strcopymem.S
Normal file
|
@ -0,0 +1,273 @@
|
||||||
|
/*-
|
||||||
|
* Copyright (c) 1997 The NetBSD Foundation, Inc.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This code is derived from software contributed to The NetBSD Foundation
|
||||||
|
* by Neil A. Carson and Mark Brinicombe
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||||
|
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||||
|
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||||
|
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
/* Taken from FreeBSD memcpy_arm.S, munged by Erbo to COMROGUE standards */
|
||||||
|
.section ".lib.text"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This is one fun bit of code ...
|
||||||
|
* Some easy listening music is suggested while trying to understand this
|
||||||
|
* code e.g. Iron Maiden
|
||||||
|
*
|
||||||
|
* For anyone attempting to understand it :
|
||||||
|
*
|
||||||
|
* The core code is implemented here with simple stubs for memcpy().
|
||||||
|
*
|
||||||
|
* All local labels are prefixed with Lmemcpy_
|
||||||
|
* Following the prefix a label starting f is used in the forward copy code
|
||||||
|
* while a label using b is used in the backwards copy code
|
||||||
|
* The source and destination addresses determine whether a forward or
|
||||||
|
* backward copy is performed.
|
||||||
|
* Separate bits of code are used to deal with the following situations
|
||||||
|
* for both the forward and backwards copy.
|
||||||
|
* unaligned source address
|
||||||
|
* unaligned destination address
|
||||||
|
* Separate copy routines are used to produce an optimised result for each
|
||||||
|
* of these cases.
|
||||||
|
* The copy code will use LDM/STM instructions to copy up to 32 bytes at
|
||||||
|
* a time where possible.
|
||||||
|
*
|
||||||
|
* Note: r12 (aka ip) can be trashed during the function along with
|
||||||
|
* r0-r3 although r0-r2 have defined uses i.e. src, dest, len through out.
|
||||||
|
* Additional registers are preserved prior to use i.e. r4, r5 & lr
|
||||||
|
*
|
||||||
|
* Apologies for the state of the comments ;-)
|
||||||
|
*/
|
||||||
|
/* Func: PVOID StrCopyMem(PVOID pDest, PCVOID pSrc, INT32 nBytes); */
|
||||||
|
/*
|
||||||
|
* Copies memory data from one block of memory to another. Assumes the memory blocks do NOT overlap.
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* - pDest = Destination for the copy operation.
|
||||||
|
* - pSrc = Source for the copy operation.
|
||||||
|
* - nBytes = Number of bytes to be copied.
|
||||||
|
*
|
||||||
|
* Returns:
|
||||||
|
* pDest.
|
||||||
|
*/
|
||||||
|
.globl StrCopyMem
|
||||||
|
StrCopyMem:
|
||||||
|
/* save leaf functions having to store this away */
|
||||||
|
stmdb sp!, {r0, lr} /* memcpy() returns dest addr */
|
||||||
|
|
||||||
|
subs r2, r2, #4
|
||||||
|
blt .Lmemcpy_l4 /* less than 4 bytes */
|
||||||
|
ands r12, r0, #3
|
||||||
|
bne .Lmemcpy_destul /* oh unaligned destination addr */
|
||||||
|
ands r12, r1, #3
|
||||||
|
bne .Lmemcpy_srcul /* oh unaligned source addr */
|
||||||
|
|
||||||
|
.Lmemcpy_t8:
|
||||||
|
/* We have aligned source and destination */
|
||||||
|
subs r2, r2, #8
|
||||||
|
blt .Lmemcpy_l12 /* less than 12 bytes (4 from above) */
|
||||||
|
subs r2, r2, #0x14
|
||||||
|
blt .Lmemcpy_l32 /* less than 32 bytes (12 from above) */
|
||||||
|
stmdb sp!, {r4} /* borrow r4 */
|
||||||
|
|
||||||
|
/* blat 32 bytes at a time */
|
||||||
|
/* XXX for really big copies perhaps we should use more registers */
|
||||||
|
.Lmemcpy_loop32:
|
||||||
|
ldmia r1!, {r3, r4, r12, lr}
|
||||||
|
stmia r0!, {r3, r4, r12, lr}
|
||||||
|
ldmia r1!, {r3, r4, r12, lr}
|
||||||
|
stmia r0!, {r3, r4, r12, lr}
|
||||||
|
subs r2, r2, #0x20
|
||||||
|
bge .Lmemcpy_loop32
|
||||||
|
|
||||||
|
cmn r2, #0x10
|
||||||
|
ldmgeia r1!, {r3, r4, r12, lr} /* blat a remaining 16 bytes */
|
||||||
|
stmgeia r0!, {r3, r4, r12, lr}
|
||||||
|
subge r2, r2, #0x10
|
||||||
|
ldmia sp!, {r4} /* return r4 */
|
||||||
|
|
||||||
|
.Lmemcpy_l32:
|
||||||
|
adds r2, r2, #0x14
|
||||||
|
|
||||||
|
/* blat 12 bytes at a time */
|
||||||
|
.Lmemcpy_loop12:
|
||||||
|
ldmgeia r1!, {r3, r12, lr}
|
||||||
|
stmgeia r0!, {r3, r12, lr}
|
||||||
|
subges r2, r2, #0x0c
|
||||||
|
bge .Lmemcpy_loop12
|
||||||
|
|
||||||
|
.Lmemcpy_l12:
|
||||||
|
adds r2, r2, #8
|
||||||
|
blt .Lmemcpy_l4
|
||||||
|
|
||||||
|
subs r2, r2, #4
|
||||||
|
ldrlt r3, [r1], #4
|
||||||
|
strlt r3, [r0], #4
|
||||||
|
ldmgeia r1!, {r3, r12}
|
||||||
|
stmgeia r0!, {r3, r12}
|
||||||
|
subge r2, r2, #4
|
||||||
|
|
||||||
|
.Lmemcpy_l4:
|
||||||
|
/* less than 4 bytes to go */
|
||||||
|
adds r2, r2, #4
|
||||||
|
ldmeqia sp!, {r0, pc} /* done */
|
||||||
|
|
||||||
|
/* copy the crud byte at a time */
|
||||||
|
cmp r2, #2
|
||||||
|
ldrb r3, [r1], #1
|
||||||
|
strb r3, [r0], #1
|
||||||
|
ldrgeb r3, [r1], #1
|
||||||
|
strgeb r3, [r0], #1
|
||||||
|
ldrgtb r3, [r1], #1
|
||||||
|
strgtb r3, [r0], #1
|
||||||
|
ldmia sp!, {r0, pc}
|
||||||
|
|
||||||
|
/* erg - unaligned destination */
|
||||||
|
.Lmemcpy_destul:
|
||||||
|
rsb r12, r12, #4
|
||||||
|
cmp r12, #2
|
||||||
|
|
||||||
|
/* align destination with byte copies */
|
||||||
|
ldrb r3, [r1], #1
|
||||||
|
strb r3, [r0], #1
|
||||||
|
ldrgeb r3, [r1], #1
|
||||||
|
strgeb r3, [r0], #1
|
||||||
|
ldrgtb r3, [r1], #1
|
||||||
|
strgtb r3, [r0], #1
|
||||||
|
subs r2, r2, r12
|
||||||
|
blt .Lmemcpy_l4 /* less the 4 bytes */
|
||||||
|
|
||||||
|
ands r12, r1, #3
|
||||||
|
beq .Lmemcpy_t8 /* we have an aligned source */
|
||||||
|
|
||||||
|
/* erg - unaligned source */
|
||||||
|
/* This is where it gets nasty ... */
|
||||||
|
.Lmemcpy_srcul:
|
||||||
|
bic r1, r1, #3
|
||||||
|
ldr lr, [r1], #4
|
||||||
|
cmp r12, #2
|
||||||
|
bgt .Lmemcpy_srcul3
|
||||||
|
beq .Lmemcpy_srcul2
|
||||||
|
cmp r2, #0x0c
|
||||||
|
blt .Lmemcpy_srcul1loop4
|
||||||
|
sub r2, r2, #0x0c
|
||||||
|
stmdb sp!, {r4, r5}
|
||||||
|
|
||||||
|
.Lmemcpy_srcul1loop16:
|
||||||
|
mov r3, lr, lsr #8
|
||||||
|
ldmia r1!, {r4, r5, r12, lr}
|
||||||
|
orr r3, r3, r4, lsl #24
|
||||||
|
mov r4, r4, lsr #8
|
||||||
|
orr r4, r4, r5, lsl #24
|
||||||
|
mov r5, r5, lsr #8
|
||||||
|
orr r5, r5, r12, lsl #24
|
||||||
|
mov r12, r12, lsr #8
|
||||||
|
orr r12, r12, lr, lsl #24
|
||||||
|
stmia r0!, {r3-r5, r12}
|
||||||
|
subs r2, r2, #0x10
|
||||||
|
bge .Lmemcpy_srcul1loop16
|
||||||
|
ldmia sp!, {r4, r5}
|
||||||
|
adds r2, r2, #0x0c
|
||||||
|
blt .Lmemcpy_srcul1l4
|
||||||
|
|
||||||
|
.Lmemcpy_srcul1loop4:
|
||||||
|
mov r12, lr, lsr #8
|
||||||
|
ldr lr, [r1], #4
|
||||||
|
orr r12, r12, lr, lsl #24
|
||||||
|
str r12, [r0], #4
|
||||||
|
subs r2, r2, #4
|
||||||
|
bge .Lmemcpy_srcul1loop4
|
||||||
|
|
||||||
|
.Lmemcpy_srcul1l4:
|
||||||
|
sub r1, r1, #3
|
||||||
|
b .Lmemcpy_l4
|
||||||
|
|
||||||
|
.Lmemcpy_srcul2:
|
||||||
|
cmp r2, #0x0c
|
||||||
|
blt .Lmemcpy_srcul2loop4
|
||||||
|
sub r2, r2, #0x0c
|
||||||
|
stmdb sp!, {r4, r5}
|
||||||
|
|
||||||
|
.Lmemcpy_srcul2loop16:
|
||||||
|
mov r3, lr, lsr #16
|
||||||
|
ldmia r1!, {r4, r5, r12, lr}
|
||||||
|
orr r3, r3, r4, lsl #16
|
||||||
|
mov r4, r4, lsr #16
|
||||||
|
orr r4, r4, r5, lsl #16
|
||||||
|
mov r5, r5, lsr #16
|
||||||
|
orr r5, r5, r12, lsl #16
|
||||||
|
mov r12, r12, lsr #16
|
||||||
|
orr r12, r12, lr, lsl #16
|
||||||
|
stmia r0!, {r3-r5, r12}
|
||||||
|
subs r2, r2, #0x10
|
||||||
|
bge .Lmemcpy_srcul2loop16
|
||||||
|
ldmia sp!, {r4, r5}
|
||||||
|
adds r2, r2, #0x0c
|
||||||
|
blt .Lmemcpy_srcul2l4
|
||||||
|
|
||||||
|
.Lmemcpy_srcul2loop4:
|
||||||
|
mov r12, lr, lsr #16
|
||||||
|
ldr lr, [r1], #4
|
||||||
|
orr r12, r12, lr, lsl #16
|
||||||
|
str r12, [r0], #4
|
||||||
|
subs r2, r2, #4
|
||||||
|
bge .Lmemcpy_srcul2loop4
|
||||||
|
|
||||||
|
.Lmemcpy_srcul2l4:
|
||||||
|
sub r1, r1, #2
|
||||||
|
b .Lmemcpy_l4
|
||||||
|
|
||||||
|
.Lmemcpy_srcul3:
|
||||||
|
cmp r2, #0x0c
|
||||||
|
blt .Lmemcpy_srcul3loop4
|
||||||
|
sub r2, r2, #0x0c
|
||||||
|
stmdb sp!, {r4, r5}
|
||||||
|
|
||||||
|
.Lmemcpy_srcul3loop16:
|
||||||
|
mov r3, lr, lsr #24
|
||||||
|
ldmia r1!, {r4, r5, r12, lr}
|
||||||
|
orr r3, r3, r4, lsl #8
|
||||||
|
mov r4, r4, lsr #24
|
||||||
|
orr r4, r4, r5, lsl #8
|
||||||
|
mov r5, r5, lsr #24
|
||||||
|
orr r5, r5, r12, lsl #8
|
||||||
|
mov r12, r12, lsr #24
|
||||||
|
orr r12, r12, lr, lsl #8
|
||||||
|
stmia r0!, {r3-r5, r12}
|
||||||
|
subs r2, r2, #0x10
|
||||||
|
bge .Lmemcpy_srcul3loop16
|
||||||
|
ldmia sp!, {r4, r5}
|
||||||
|
adds r2, r2, #0x0c
|
||||||
|
blt .Lmemcpy_srcul3l4
|
||||||
|
|
||||||
|
.Lmemcpy_srcul3loop4:
|
||||||
|
mov r12, lr, lsr #24
|
||||||
|
ldr lr, [r1], #4
|
||||||
|
orr r12, r12, lr, lsl #8
|
||||||
|
str r12, [r0], #4
|
||||||
|
subs r2, r2, #4
|
||||||
|
bge .Lmemcpy_srcul3loop4
|
||||||
|
|
||||||
|
.Lmemcpy_srcul3l4:
|
||||||
|
sub r1, r1, #1
|
||||||
|
b .Lmemcpy_l4
|
290
kernel/trace.c
Normal file
290
kernel/trace.c
Normal file
|
@ -0,0 +1,290 @@
|
||||||
|
/*
|
||||||
|
* This file is part of the COMROGUE Operating System for Raspberry Pi
|
||||||
|
*
|
||||||
|
* Copyright (c) 2013, Eric J. Bowersox / Erbosoft Enterprises
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This program is free for commercial and non-commercial use as long as the following conditions are
|
||||||
|
* adhered to.
|
||||||
|
*
|
||||||
|
* Copyright in this file remains Eric J. Bowersox and/or Erbosoft, and as such any copyright notices
|
||||||
|
* in the code are not to be removed.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification, are permitted
|
||||||
|
* provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* * Redistributions of source code must retain the above copyright notice, this list of conditions and
|
||||||
|
* the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
|
||||||
|
* the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
|
||||||
|
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||||
|
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||||
|
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* "Raspberry Pi" is a trademark of the Raspberry Pi Foundation.
|
||||||
|
*/
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <comrogue/types.h>
|
||||||
|
#include <comrogue/str.h>
|
||||||
|
#include <comrogue/internals/seg.h>
|
||||||
|
#include <comrogue/internals/llio.h>
|
||||||
|
#include <comrogue/internals/auxdev.h>
|
||||||
|
#include <comrogue/internals/gpio.h>
|
||||||
|
#include <comrogue/internals/16550.h>
|
||||||
|
|
||||||
|
/* Hex digits. */
|
||||||
|
static DECLARE_STRING8_CONST(szHexDigits, "0123456789ABCDEF");
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initializes the trace functionality (the aux UART).
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* None.
|
||||||
|
*
|
||||||
|
* Returns:
|
||||||
|
* Nothing.
|
||||||
|
*
|
||||||
|
* Side effects:
|
||||||
|
* GPIO 14 configured for output from UART1; UART1 initialized to 115200 8N1 and enabled for output.
|
||||||
|
*/
|
||||||
|
void TrInit(void)
|
||||||
|
{
|
||||||
|
register UINT32 ra;
|
||||||
|
|
||||||
|
/* Initialize UART */
|
||||||
|
llIOWrite(AUX_REG_ENABLE, AUX_ENABLE_MU); /* enable UART1 */
|
||||||
|
llIOWrite(AUX_MU_REG_IER, 0);
|
||||||
|
llIOWrite(AUX_MU_REG_CNTL, 0);
|
||||||
|
llIOWrite(AUX_MU_REG_LCR, U16550_LCR_LENGTH_8|U16550_LCR_PARITY_NONE); /* 8 bits, no parity */
|
||||||
|
llIOWrite(AUX_MU_REG_MCR, 0);
|
||||||
|
llIOWrite(AUX_MU_REG_IER, 0);
|
||||||
|
llIOWrite(AUX_MU_REG_FCR, U16550_FCR_RXCLEAR|U16550_FCR_TXCLEAR|U16550_FCR_LEVEL_14);
|
||||||
|
llIOWrite(AUX_MU_REG_BAUD, 270); /* 115200 baud */
|
||||||
|
ra = llIORead(GPFSEL1_REG);
|
||||||
|
ra &= ~GP_FUNC_MASK(4); /* GPIO 14 - connects to pin 8 on GPIO connector */
|
||||||
|
ra |= GP_FUNC_BITS(4, GP_PIN_ALT5); /* Alt function 5 - UART1 TxD */
|
||||||
|
llIOWrite(GPFSEL1_REG, ra);
|
||||||
|
llIOWrite(GPPUD_REG, 0);
|
||||||
|
llIODelay(150);
|
||||||
|
llIOWrite(GPPUDCLK0_REG, GP_BIT(14));
|
||||||
|
llIODelay(150);
|
||||||
|
llIOWrite(GPPUDCLK0_REG, 0);
|
||||||
|
llIOWrite(AUX_MU_REG_CNTL, AUXMU_CNTL_TXENABLE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Makes sure all trace output has been flushed out the UART.
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* None.
|
||||||
|
*
|
||||||
|
* Returns:
|
||||||
|
* Nothing.
|
||||||
|
*
|
||||||
|
* Side effects:
|
||||||
|
* UART1 transmitter is empty upon return from this function.
|
||||||
|
*/
|
||||||
|
static void flush_trace(void)
|
||||||
|
{
|
||||||
|
register UINT32 lsr = llIORead(AUX_MU_REG_LSR);
|
||||||
|
while (!(lsr & U16550_LSR_TXEMPTY))
|
||||||
|
lsr = llIORead(AUX_MU_REG_LSR);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Writes a raw character to trace output.
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* - c = The character to be written.
|
||||||
|
*
|
||||||
|
* Returns:
|
||||||
|
* Nothing.
|
||||||
|
*
|
||||||
|
* Side effects:
|
||||||
|
* Character written to UART1.
|
||||||
|
*/
|
||||||
|
static void write_trace(UINT32 c)
|
||||||
|
{
|
||||||
|
flush_trace();
|
||||||
|
llIOWrite(AUX_MU_REG_THR, c);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Writes a character to trace output, translating newlines.
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* - c = The character to be written.
|
||||||
|
*
|
||||||
|
* Returns:
|
||||||
|
* Nothing.
|
||||||
|
*
|
||||||
|
* Side effects:
|
||||||
|
* Either 1 or 2 characters written to UART1.
|
||||||
|
*/
|
||||||
|
void TrWriteChar8(CHAR c)
|
||||||
|
{
|
||||||
|
if (c == '\n')
|
||||||
|
write_trace('\r');
|
||||||
|
write_trace((UINT32)c);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Writes a null-terminated string to trace output. Newlines in the string are translated.
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* - psz = Pointer to string to be written.
|
||||||
|
*
|
||||||
|
* Returns:
|
||||||
|
* Nothing.
|
||||||
|
*
|
||||||
|
* Side effects:
|
||||||
|
* Characters in string written to UART1.
|
||||||
|
*/
|
||||||
|
void TrWriteString8(PCSTR psz)
|
||||||
|
{
|
||||||
|
while (*psz)
|
||||||
|
TrWriteChar8(*psz++);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Writes the value of a 32-bit word to trace output.
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* - uiValue = Value to be written to trace output.
|
||||||
|
*
|
||||||
|
* Returns:
|
||||||
|
* Nothing.
|
||||||
|
*
|
||||||
|
* Side effects:
|
||||||
|
* 8 characters written to UART1.
|
||||||
|
*/
|
||||||
|
void TrWriteWord(UINT32 uiValue)
|
||||||
|
{
|
||||||
|
register UINT32 uiShift = 32;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
uiShift -= 4;
|
||||||
|
write_trace(szHexDigits[(uiValue >> uiShift) & 0xF]);
|
||||||
|
} while (uiShift > 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Used by the "trace printf" functions to actually output character data.
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* - pDummy = Always points to a NULL value; not used.
|
||||||
|
* - pchData = Pointer to the data to be written.
|
||||||
|
* - cchData = The number of characters to be written.
|
||||||
|
*
|
||||||
|
* Returns:
|
||||||
|
* S_OK in all circumstances.
|
||||||
|
*
|
||||||
|
* Side effects:
|
||||||
|
* cchData characters written to UART1.
|
||||||
|
*/
|
||||||
|
static HRESULT write_trace_buf8(PPVOID pDummy, PCCHAR pchData, UINT32 cchData)
|
||||||
|
{
|
||||||
|
register UINT32 i;
|
||||||
|
for (i=0; i<cchData; i++)
|
||||||
|
TrWriteChar8(pchData[i]);
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Formats output to the trace output.
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* - pszFormat = Format string for the output, like a printf format string.
|
||||||
|
* - pargs = Pointer to varargs-style function arguments.
|
||||||
|
*
|
||||||
|
* Returns:
|
||||||
|
* A HRESULT as follows: Severity indicates whether the output function failed or succeeded, facility is always
|
||||||
|
* FACILITY_STRFORMAT, code indicates the number of characters output.
|
||||||
|
*
|
||||||
|
* Side effects:
|
||||||
|
* Characters written to UART1, the count of which is given by the output code.
|
||||||
|
*/
|
||||||
|
HRESULT TrVPrintf8(PCSTR pszFormat, va_list pargs)
|
||||||
|
{
|
||||||
|
return StrFormatV8(write_trace_buf8, NULL, pszFormat, pargs);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Formats output to the trace output.
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* - pszFormat = Format string for the output, like a printf format string.
|
||||||
|
* - <args> = Arguments to be substitute dinto the format string.
|
||||||
|
*
|
||||||
|
* Returns:
|
||||||
|
* A HRESULT as follows: Severity indicates whether the output function failed or succeeded, facility is always
|
||||||
|
* FACILITY_STRFORMAT, code indicates the number of characters output.
|
||||||
|
*
|
||||||
|
* Side effects:
|
||||||
|
* Characters written to UART1, the count of which is given by the output code.
|
||||||
|
*/
|
||||||
|
HRESULT TrPrintf8(PCSTR pszFormat, ...)
|
||||||
|
{
|
||||||
|
HRESULT hr;
|
||||||
|
va_list argp;
|
||||||
|
va_start(argp, pszFormat);
|
||||||
|
hr = StrFormatV8(write_trace_buf8, NULL, pszFormat, argp);
|
||||||
|
va_end(argp);
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Prints an "assertion failed" message to trace output.
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* - pszFile = The file name the assertion was declared in.
|
||||||
|
* - nLine = The line number the assertion was declared at.
|
||||||
|
*
|
||||||
|
* Returns:
|
||||||
|
* Nothing.
|
||||||
|
*
|
||||||
|
* Side effects:
|
||||||
|
* Characters written to UART1.
|
||||||
|
*/
|
||||||
|
void TrAssertFailed(PCSTR pszFile, INT32 nLine)
|
||||||
|
{
|
||||||
|
static DECLARE_STRING8_CONST(szMessage, "*** ASSERTION FAILED at %s:%d\n");
|
||||||
|
TrPrintf8(szMessage, pszFile, nLine);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Puts the CPU into a loop where it blinks the green ACTIVITY light forever.
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* None.
|
||||||
|
*
|
||||||
|
* Returns:
|
||||||
|
* DOES NOT RETURN!
|
||||||
|
*
|
||||||
|
* Side effects:
|
||||||
|
* GPIO 16 configured for output and turns on and off indefinitely.
|
||||||
|
*/
|
||||||
|
void TrInfiniBlink(void)
|
||||||
|
{
|
||||||
|
register UINT32 ra;
|
||||||
|
|
||||||
|
flush_trace();
|
||||||
|
ra = llIORead(GPFSEL1_REG);
|
||||||
|
ra &= GP_FUNC_MASK(6); /* GPIO 16 - connects to green ACTIVITY LED */
|
||||||
|
ra |= GP_FUNC_BITS(6, GP_PIN_OUTPUT); /* output in all circumstances */
|
||||||
|
llIOWrite(GPFSEL1_REG, ra);
|
||||||
|
|
||||||
|
for(;;)
|
||||||
|
{
|
||||||
|
llIOWrite(GPSET0_REG, GP_BIT(16));
|
||||||
|
llIODelay(0x100000);
|
||||||
|
llIOWrite(GPCLR0_REG, GP_BIT(16));
|
||||||
|
llIODelay(0x100000);
|
||||||
|
}
|
||||||
|
}
|
43
tools/Makefile
Normal file
43
tools/Makefile
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
#
|
||||||
|
# This file is part of the COMROGUE Operating System for Raspberry Pi
|
||||||
|
#
|
||||||
|
# Copyright (c) 2013, Eric J. Bowersox / Erbosoft Enterprises
|
||||||
|
# All rights reserved.
|
||||||
|
#
|
||||||
|
# This program is free for commercial and non-commercial use as long as the following conditions are
|
||||||
|
# adhered to.
|
||||||
|
#
|
||||||
|
# Copyright in this file remains Eric J. Bowersox and/or Erbosoft, and as such any copyright notices
|
||||||
|
# in the code are not to be removed.
|
||||||
|
#
|
||||||
|
# Redistribution and use in source and binary forms, with or without modification, are permitted
|
||||||
|
# provided that the following conditions are met:
|
||||||
|
#
|
||||||
|
# * Redistributions of source code must retain the above copyright notice, this list of conditions and
|
||||||
|
# the following disclaimer.
|
||||||
|
# * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
|
||||||
|
# the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||||
|
#
|
||||||
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
|
||||||
|
# WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||||
|
# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||||
|
# TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
# POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
#
|
||||||
|
# "Raspberry Pi" is a trademark of the Raspberry Pi Foundation.
|
||||||
|
|
||||||
|
MAKEFLAGS += -rR
|
||||||
|
|
||||||
|
all: pidl
|
||||||
|
|
||||||
|
pidl:
|
||||||
|
(cd pidl && perl Makefile.PL && make)
|
||||||
|
|
||||||
|
clean:
|
||||||
|
(if [ -f pidl/Makefile ]; then make -C pidl clean; fi)
|
||||||
|
-rm pidl/Makefile.old
|
||||||
|
|
||||||
|
.PHONY: pidl
|
6
tools/README
Normal file
6
tools/README
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
Notes regarding the contents of this directory:
|
||||||
|
|
||||||
|
pidl
|
||||||
|
----
|
||||||
|
This utility was taken from the Samba 4 sources (git://git.samba.org/samba.git, subdirectory pidl/) and
|
||||||
|
modified for use with COMROGUE. It and all modifications made to it are distributable under the GNU GPL.
|
41
tools/pidl/MANIFEST
Normal file
41
tools/pidl/MANIFEST
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
MANIFEST
|
||||||
|
tests/parse_idl.pl
|
||||||
|
tests/Util.pm
|
||||||
|
tests/ndr_refptr.pl
|
||||||
|
tests/ndr_string.pl
|
||||||
|
tests/ndr_simple.pl
|
||||||
|
tests/ndr_align.pl
|
||||||
|
tests/ndr_alloc.pl
|
||||||
|
tests/ndr_array.pl
|
||||||
|
tests/ndr.pl
|
||||||
|
tests/samba-ndr.pl
|
||||||
|
tests/util.pl
|
||||||
|
tests/test_util.pl
|
||||||
|
tests/ndr_represent.pl
|
||||||
|
tests/ndr_compat.pl
|
||||||
|
tests/ndr_fullptr.pl
|
||||||
|
tests/ndr_tagtype.pl
|
||||||
|
tests/header.pl
|
||||||
|
lib/Parse/Pidl/Samba3/ClientNDR.pm
|
||||||
|
lib/Parse/Pidl/Samba3/ServerNDR.pm
|
||||||
|
lib/Parse/Pidl/Samba4/NDR/Server.pm
|
||||||
|
lib/Parse/Pidl/Samba4/NDR/Parser.pm
|
||||||
|
lib/Parse/Pidl/Samba4/NDR/Client.pm
|
||||||
|
lib/Parse/Pidl/Samba4/Header.pm
|
||||||
|
lib/Parse/Pidl/Samba4/TDR.pm
|
||||||
|
lib/Parse/Pidl/Samba4/Template.pm
|
||||||
|
lib/Parse/Pidl/Samba4.pm
|
||||||
|
lib/Parse/Pidl/Wireshark/Conformance.pm
|
||||||
|
lib/Parse/Pidl/Wireshark/NDR.pm
|
||||||
|
lib/Parse/Pidl/Typelist.pm
|
||||||
|
lib/Parse/Pidl/Dump.pm
|
||||||
|
lib/Parse/Pidl/Compat.pm
|
||||||
|
lib/Parse/Pidl/Util.pm
|
||||||
|
lib/Parse/Pidl/NDR.pm
|
||||||
|
lib/Parse/Pidl.pm
|
||||||
|
Makefile.PL
|
||||||
|
idl.yp
|
||||||
|
TODO
|
||||||
|
README
|
||||||
|
pidl
|
||||||
|
META.yml
|
18
tools/pidl/META.yml
Normal file
18
tools/pidl/META.yml
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
name: Parse-Pidl
|
||||||
|
abstract: Generate parsers / DCE/RPC-clients from IDL
|
||||||
|
author:
|
||||||
|
- Andrew Tridgell <tridge@samba.org>
|
||||||
|
- Jelmer Vernooij <jelmer@samba.org>
|
||||||
|
- Stefan Metzmacher <metze@samba.org>
|
||||||
|
- Tim Potter <tpot@samba.org>
|
||||||
|
license: gplv3
|
||||||
|
installdirs: site
|
||||||
|
homepage: http://www.samba.org/
|
||||||
|
bugtracker: http://bugzilla.samba.org/
|
||||||
|
requires:
|
||||||
|
Parse::Yapp: 0
|
||||||
|
recommends:
|
||||||
|
Data::Dumper: 0
|
||||||
|
meta-spec:
|
||||||
|
version: 1.3
|
||||||
|
url: http://module-build.sourceforge.net/META-spec-v1.3.html
|
17
tools/pidl/Makefile.PL
Executable file
17
tools/pidl/Makefile.PL
Executable file
|
@ -0,0 +1,17 @@
|
||||||
|
use ExtUtils::MakeMaker;
|
||||||
|
WriteMakefile(
|
||||||
|
'NAME' => 'Parse::Pidl',
|
||||||
|
'VERSION_FROM' => 'lib/Parse/Pidl.pm',
|
||||||
|
'EXE_FILES' => [ 'pidl' ],
|
||||||
|
'test' => { 'TESTS' => 'tests/*.pl' }
|
||||||
|
);
|
||||||
|
|
||||||
|
sub MY::postamble {
|
||||||
|
<<'EOT';
|
||||||
|
lib/Parse/Pidl/IDL.pm: idl.yp
|
||||||
|
yapp -m 'Parse::Pidl::IDL' -o lib/Parse/Pidl/IDL.pm idl.yp
|
||||||
|
|
||||||
|
lib/Parse/Pidl/Expr.pm: expr.yp
|
||||||
|
yapp -m 'Parse::Pidl::Expr' -o lib/Parse/Pidl/Expr.pm expr.yp
|
||||||
|
EOT
|
||||||
|
}
|
63
tools/pidl/README
Normal file
63
tools/pidl/README
Normal file
|
@ -0,0 +1,63 @@
|
||||||
|
Introduction:
|
||||||
|
=============
|
||||||
|
This directory contains the source code of the pidl (Perl IDL)
|
||||||
|
compiler for Samba 4.
|
||||||
|
|
||||||
|
The main sources for pidl are available using Git as part of
|
||||||
|
the combined Samba 3 / Samba 4 tree. Use:
|
||||||
|
git clone git://git.samba.org/samba.git
|
||||||
|
|
||||||
|
Pidl works by building a parse tree from a .pidl file (a simple
|
||||||
|
dump of it's internal parse tree) or a .idl file
|
||||||
|
(a file format mostly like the IDL file format midl uses).
|
||||||
|
The IDL file parser is in idl.yp (a yacc file converted to
|
||||||
|
perl code by yapp)
|
||||||
|
|
||||||
|
After a parse tree is present, pidl will call one of it's backends
|
||||||
|
(which one depends on the options given on the command-line). Here is
|
||||||
|
a list of current backends:
|
||||||
|
|
||||||
|
Standalone installation:
|
||||||
|
========================
|
||||||
|
Run Makefile.PL to generate the Makefile.
|
||||||
|
|
||||||
|
Then run "make install" (as root) to install.
|
||||||
|
|
||||||
|
Internals overview:
|
||||||
|
===================
|
||||||
|
|
||||||
|
-- Generic --
|
||||||
|
Parse::Pidl::Dump - Converts the parse tree back to an IDL file
|
||||||
|
Parse::Pidl::Samba4::Header - Generates header file with data structures defined in IDL file
|
||||||
|
Parse::Pidl::NDR - Generates intermediate datastructures for use by NDR parses/generators
|
||||||
|
Parse::Pidl::ODL - Generates IDL structures from ODL structures for use in the NDR parser generator
|
||||||
|
Parse::Pidl::Test - Utility functions for use in pidl's testsuite
|
||||||
|
|
||||||
|
-- Samba NDR --
|
||||||
|
Parse::Pidl::Samba4::NDR::Client - Generates client call functions in C using the NDR parser
|
||||||
|
Parse::Pidl::Samba4::NDR::Parser - Generates pull/push functions for parsing NDR
|
||||||
|
Parse::Pidl::Samba4::NDR::Server - Generates server side implementation in C
|
||||||
|
Parse::Pidl::Samba4::TDR - Parser generator for the "Trivial Data Representation"
|
||||||
|
Parse::Pidl::Samba4::Template - Generates stubs in C for server implementation
|
||||||
|
Parse::Pidl::Samba4::Python - Generates bindings for Python
|
||||||
|
|
||||||
|
-- Samba COM / DCOM --
|
||||||
|
Parse::Pidl::Samba4::COM::Proxy - Generates proxy object for DCOM (client-side)
|
||||||
|
Parse::Pidl::Samba4::COM::Stub - Generates stub call handler for DCOM (server-side)
|
||||||
|
Parse::Pidl::Samba4::COM::Header - Generates headers for COM
|
||||||
|
|
||||||
|
-- Wireshark --
|
||||||
|
Parse::Pidl::Wireshark::NDR - Generates a parser for the Wireshark network sniffer
|
||||||
|
Parse::Pidl::Wireshark::Conformance - Reads conformance files containing additional data for generating Wireshark parsers
|
||||||
|
|
||||||
|
-- Utility modules --
|
||||||
|
Parse::Pidl::Util - Misc utility functions used by *.pm and pidl.pl
|
||||||
|
Parse::Pidl::Typelist - Utility functions for keeping track of known types and their representation in C
|
||||||
|
|
||||||
|
Tips for hacking on pidl:
|
||||||
|
- Look at the pidl's parse tree by using the --keep option and looking
|
||||||
|
at the generated .pidl file.
|
||||||
|
- The various backends have a lot in common, if you don't understand how one
|
||||||
|
implements something, look at the others
|
||||||
|
- See pidl(1) and the documentation on midl
|
||||||
|
- See 'info bison' and yapp(1) for information on the file format of idl.yp
|
44
tools/pidl/TODO
Normal file
44
tools/pidl/TODO
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
- warn when union instances don't have a discriminant
|
||||||
|
|
||||||
|
- true multiple dimension array / strings in arrays support
|
||||||
|
|
||||||
|
- compatibility mode for generating MIDL-readable data:
|
||||||
|
- strip out pidl-specific properties
|
||||||
|
|
||||||
|
- make bitmap an optional attribute on enum
|
||||||
|
- support nested elements
|
||||||
|
- support typedefs properly (e.g. allow "typedef void **bla;")
|
||||||
|
- make typedefs generate real typedefs
|
||||||
|
- improve represent_as(): allow it to be used for arrays and other complex
|
||||||
|
types
|
||||||
|
|
||||||
|
- --explain-ndr option that dumps out parse tree ?
|
||||||
|
|
||||||
|
- seperate tables for NDR and DCE/RPC
|
||||||
|
- maybe no tables for NDR at all? we only need them for ndrdump
|
||||||
|
and that can use dlsym()
|
||||||
|
|
||||||
|
- allow data structures outside of interfaces
|
||||||
|
|
||||||
|
- mem_ctx in the interface rather than as struct ndr member.
|
||||||
|
|
||||||
|
- real typelibs
|
||||||
|
|
||||||
|
- fix [in,out] handling and allocation for samba3:
|
||||||
|
- add inout
|
||||||
|
- make NULL to mean "allocate me"
|
||||||
|
- remove NDR_AUTO_REF_ALLOC flag
|
||||||
|
|
||||||
|
- automatic test generator based on IDL pointer types
|
||||||
|
|
||||||
|
- support converting structs to tuples in Python rather than objects
|
||||||
|
- convert structs with a single mattering member to that member directly, e.g.:
|
||||||
|
struct bar {
|
||||||
|
int size;
|
||||||
|
[size_is(size)] uint32 *array;
|
||||||
|
};
|
||||||
|
|
||||||
|
should be converted to an array of uint32's
|
||||||
|
|
||||||
|
- python: fill in size members automatically in some places if the struct isn't being returned
|
||||||
|
(so we don't have to cope with the array growing)
|
202
tools/pidl/expr.yp
Normal file
202
tools/pidl/expr.yp
Normal file
|
@ -0,0 +1,202 @@
|
||||||
|
# expr.yp
|
||||||
|
# Copyright (C) 2006 Jelmer Vernooij <jelmer@samba.org>
|
||||||
|
# Published under the GNU GPL
|
||||||
|
#
|
||||||
|
%left '->'
|
||||||
|
%right '!' '~'
|
||||||
|
%left '*' '/' '%'
|
||||||
|
%left '+' '-'
|
||||||
|
%left '<<' '>>'
|
||||||
|
%left '>' '<'
|
||||||
|
%left '==' '!='
|
||||||
|
%left '&'
|
||||||
|
%left '|'
|
||||||
|
%left '&&'
|
||||||
|
%left '||'
|
||||||
|
%left '?' ':'
|
||||||
|
%left NEG DEREF ADDROF INV
|
||||||
|
%left '.'
|
||||||
|
|
||||||
|
%%
|
||||||
|
exp:
|
||||||
|
NUM
|
||||||
|
|
|
||||||
|
TEXT { "\"$_[1]\"" }
|
||||||
|
|
|
||||||
|
func
|
||||||
|
|
|
||||||
|
var
|
||||||
|
|
|
||||||
|
'~' exp %prec INV { "~$_[2]" }
|
||||||
|
|
|
||||||
|
exp '+' exp { "$_[1] + $_[3]" }
|
||||||
|
|
|
||||||
|
exp '-' exp { "$_[1] - $_[3]" }
|
||||||
|
|
|
||||||
|
exp '*' exp { "$_[1] * $_[3]" }
|
||||||
|
|
|
||||||
|
exp '%' exp { "$_[1] % $_[3]" }
|
||||||
|
|
|
||||||
|
exp '<' exp { "$_[1] < $_[3]" }
|
||||||
|
|
|
||||||
|
exp '>' exp { "$_[1] > $_[3]" }
|
||||||
|
|
|
||||||
|
exp '|' exp { "$_[1] | $_[3]" }
|
||||||
|
|
|
||||||
|
exp '==' exp { "$_[1] == $_[3]" }
|
||||||
|
|
|
||||||
|
exp '<=' exp { "$_[1] <= $_[3]" }
|
||||||
|
|
|
||||||
|
exp '=>' exp { "$_[1] => $_[3]" }
|
||||||
|
|
|
||||||
|
exp '<<' exp { "$_[1] << $_[3]" }
|
||||||
|
|
|
||||||
|
exp '>>' exp { "$_[1] >> $_[3]" }
|
||||||
|
|
|
||||||
|
exp '!=' exp { "$_[1] != $_[3]" }
|
||||||
|
|
|
||||||
|
exp '||' exp { "$_[1] || $_[3]" }
|
||||||
|
|
|
||||||
|
exp '&&' exp { "$_[1] && $_[3]" }
|
||||||
|
|
|
||||||
|
exp '&' exp { "$_[1] & $_[3]" }
|
||||||
|
|
|
||||||
|
exp '?' exp ':' exp { "$_[1]?$_[3]:$_[5]" }
|
||||||
|
|
|
||||||
|
'~' exp { "~$_[1]" }
|
||||||
|
|
|
||||||
|
'!' exp { "not $_[1]" }
|
||||||
|
|
|
||||||
|
exp '/' exp { "$_[1] / $_[3]" }
|
||||||
|
|
|
||||||
|
'-' exp %prec NEG { "-$_[2]" }
|
||||||
|
|
|
||||||
|
'&' exp %prec ADDROF { "&$_[2]" }
|
||||||
|
|
|
||||||
|
exp '^' exp { "$_[1]^$_[3]" }
|
||||||
|
|
|
||||||
|
'(' exp ')' { "($_[2])" }
|
||||||
|
;
|
||||||
|
|
||||||
|
possible_pointer:
|
||||||
|
VAR { $_[0]->_Lookup($_[1]) }
|
||||||
|
|
|
||||||
|
'*' possible_pointer %prec DEREF { $_[0]->_Dereference($_[2]); "*$_[2]" }
|
||||||
|
;
|
||||||
|
|
||||||
|
var:
|
||||||
|
possible_pointer { $_[0]->_Use($_[1]) }
|
||||||
|
|
|
||||||
|
var '.' VAR { $_[0]->_Use("$_[1].$_[3]") }
|
||||||
|
|
|
||||||
|
'(' var ')' { "($_[2])" }
|
||||||
|
|
|
||||||
|
var '->' VAR { $_[0]->_Use("*$_[1]"); $_[1]."->".$_[3] }
|
||||||
|
;
|
||||||
|
|
||||||
|
|
||||||
|
func:
|
||||||
|
VAR '(' opt_args ')' { "$_[1]($_[3])" }
|
||||||
|
;
|
||||||
|
|
||||||
|
opt_args:
|
||||||
|
#empty
|
||||||
|
{ "" }
|
||||||
|
|
|
||||||
|
args
|
||||||
|
;
|
||||||
|
|
||||||
|
exp_or_possible_pointer:
|
||||||
|
exp
|
||||||
|
|
|
||||||
|
possible_pointer
|
||||||
|
;
|
||||||
|
|
||||||
|
args:
|
||||||
|
exp_or_possible_pointer
|
||||||
|
|
|
||||||
|
exp_or_possible_pointer ',' args { "$_[1], $_[3]" }
|
||||||
|
;
|
||||||
|
|
||||||
|
%%
|
||||||
|
|
||||||
|
package Parse::Pidl::Expr;
|
||||||
|
|
||||||
|
sub _Lexer {
|
||||||
|
my($parser)=shift;
|
||||||
|
|
||||||
|
$parser->YYData->{INPUT}=~s/^[ \t]//;
|
||||||
|
|
||||||
|
for ($parser->YYData->{INPUT}) {
|
||||||
|
if (s/^(0x[0-9A-Fa-f]+)//) {
|
||||||
|
$parser->YYData->{LAST_TOKEN} = $1;
|
||||||
|
return('NUM',$1);
|
||||||
|
}
|
||||||
|
if (s/^([0-9]+(?:\.[0-9]+)?)//) {
|
||||||
|
$parser->YYData->{LAST_TOKEN} = $1;
|
||||||
|
return('NUM',$1);
|
||||||
|
}
|
||||||
|
if (s/^([A-Za-z_][A-Za-z0-9_]*)//) {
|
||||||
|
$parser->YYData->{LAST_TOKEN} = $1;
|
||||||
|
return('VAR',$1);
|
||||||
|
}
|
||||||
|
if (s/^\"(.*?)\"//) {
|
||||||
|
$parser->YYData->{LAST_TOKEN} = $1;
|
||||||
|
return('TEXT',$1);
|
||||||
|
}
|
||||||
|
if (s/^(==|!=|<=|>=|->|\|\||<<|>>|&&)//s) {
|
||||||
|
$parser->YYData->{LAST_TOKEN} = $1;
|
||||||
|
return($1,$1);
|
||||||
|
}
|
||||||
|
if (s/^(.)//s) {
|
||||||
|
$parser->YYData->{LAST_TOKEN} = $1;
|
||||||
|
return($1,$1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sub _Use($$)
|
||||||
|
{
|
||||||
|
my ($self, $x) = @_;
|
||||||
|
if (defined($self->YYData->{USE})) {
|
||||||
|
return $self->YYData->{USE}->($x);
|
||||||
|
}
|
||||||
|
return $x;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub _Lookup($$)
|
||||||
|
{
|
||||||
|
my ($self, $x) = @_;
|
||||||
|
return $self->YYData->{LOOKUP}->($x);
|
||||||
|
}
|
||||||
|
|
||||||
|
sub _Dereference($$)
|
||||||
|
{
|
||||||
|
my ($self, $x) = @_;
|
||||||
|
if (defined($self->YYData->{DEREFERENCE})) {
|
||||||
|
$self->YYData->{DEREFERENCE}->($x);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sub _Error($)
|
||||||
|
{
|
||||||
|
my ($self) = @_;
|
||||||
|
if (defined($self->YYData->{LAST_TOKEN})) {
|
||||||
|
$self->YYData->{ERROR}->("Parse error in `".$self->YYData->{FULL_INPUT}."' near `". $self->YYData->{LAST_TOKEN} . "'");
|
||||||
|
} else {
|
||||||
|
$self->YYData->{ERROR}->("Parse error in `".$self->YYData->{FULL_INPUT}."'");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sub Run {
|
||||||
|
my($self, $data, $error, $lookup, $deref, $use) = @_;
|
||||||
|
|
||||||
|
$self->YYData->{FULL_INPUT} = $data;
|
||||||
|
$self->YYData->{INPUT} = $data;
|
||||||
|
$self->YYData->{LOOKUP} = $lookup;
|
||||||
|
$self->YYData->{DEREFERENCE} = $deref;
|
||||||
|
$self->YYData->{ERROR} = $error;
|
||||||
|
$self->YYData->{USE} = $use;
|
||||||
|
|
||||||
|
return $self->YYParse( yylex => \&_Lexer, yyerror => \&_Error);
|
||||||
|
}
|
699
tools/pidl/idl.yp
Normal file
699
tools/pidl/idl.yp
Normal file
|
@ -0,0 +1,699 @@
|
||||||
|
########################
|
||||||
|
# IDL Parse::Yapp parser
|
||||||
|
# Copyright (C) Andrew Tridgell <tridge@samba.org>
|
||||||
|
# released under the GNU GPL version 3 or later
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# the precedence actually doesn't matter at all for this grammar, but
|
||||||
|
# by providing a precedence we reduce the number of conflicts
|
||||||
|
# enormously
|
||||||
|
%left '-' '+' '&' '|' '*' '>' '.' '/' '(' ')' '[' ',' ';'
|
||||||
|
|
||||||
|
|
||||||
|
################
|
||||||
|
# grammar
|
||||||
|
%%
|
||||||
|
idl:
|
||||||
|
#empty { {} }
|
||||||
|
|
|
||||||
|
idl interface { push(@{$_[1]}, $_[2]); $_[1] }
|
||||||
|
|
|
||||||
|
idl coclass { push(@{$_[1]}, $_[2]); $_[1] }
|
||||||
|
|
|
||||||
|
idl import { push(@{$_[1]}, $_[2]); $_[1] }
|
||||||
|
|
|
||||||
|
idl include { push(@{$_[1]}, $_[2]); $_[1] }
|
||||||
|
|
|
||||||
|
idl importlib { push(@{$_[1]}, $_[2]); $_[1] }
|
||||||
|
|
|
||||||
|
idl cpp_quote { push(@{$_[1]}, $_[2]); $_[1] }
|
||||||
|
;
|
||||||
|
|
||||||
|
import:
|
||||||
|
'import' commalist ';'
|
||||||
|
{{
|
||||||
|
"TYPE" => "IMPORT",
|
||||||
|
"PATHS" => $_[2],
|
||||||
|
"FILE" => $_[0]->YYData->{FILE},
|
||||||
|
"LINE" => $_[0]->YYData->{LINE},
|
||||||
|
}}
|
||||||
|
;
|
||||||
|
|
||||||
|
include:
|
||||||
|
'include' commalist ';'
|
||||||
|
{{
|
||||||
|
"TYPE" => "INCLUDE",
|
||||||
|
"PATHS" => $_[2],
|
||||||
|
"FILE" => $_[0]->YYData->{FILE},
|
||||||
|
"LINE" => $_[0]->YYData->{LINE},
|
||||||
|
}}
|
||||||
|
;
|
||||||
|
|
||||||
|
importlib:
|
||||||
|
'importlib' commalist ';'
|
||||||
|
{{
|
||||||
|
"TYPE" => "IMPORTLIB",
|
||||||
|
"PATHS" => $_[2],
|
||||||
|
"FILE" => $_[0]->YYData->{FILE},
|
||||||
|
"LINE" => $_[0]->YYData->{LINE},
|
||||||
|
}}
|
||||||
|
;
|
||||||
|
|
||||||
|
commalist:
|
||||||
|
text { [ $_[1] ] }
|
||||||
|
|
|
||||||
|
commalist ',' text { push(@{$_[1]}, $_[3]); $_[1] }
|
||||||
|
;
|
||||||
|
|
||||||
|
coclass:
|
||||||
|
property_list 'coclass' identifier '{' interface_names '}' optional_semicolon
|
||||||
|
{{
|
||||||
|
"TYPE" => "COCLASS",
|
||||||
|
"PROPERTIES" => $_[1],
|
||||||
|
"NAME" => $_[3],
|
||||||
|
"DATA" => $_[5],
|
||||||
|
"FILE" => $_[0]->YYData->{FILE},
|
||||||
|
"LINE" => $_[0]->YYData->{LINE},
|
||||||
|
}}
|
||||||
|
;
|
||||||
|
|
||||||
|
interface_names:
|
||||||
|
#empty { {} }
|
||||||
|
|
|
||||||
|
interface_names 'interface' identifier ';' { push(@{$_[1]}, $_[2]); $_[1] }
|
||||||
|
;
|
||||||
|
|
||||||
|
interface:
|
||||||
|
property_list 'interface' identifier base_interface '{' definitions '}' optional_semicolon
|
||||||
|
{{
|
||||||
|
"TYPE" => "INTERFACE",
|
||||||
|
"PROPERTIES" => $_[1],
|
||||||
|
"NAME" => $_[3],
|
||||||
|
"BASE" => $_[4],
|
||||||
|
"DATA" => $_[6],
|
||||||
|
"FILE" => $_[0]->YYData->{FILE},
|
||||||
|
"LINE" => $_[0]->YYData->{LINE},
|
||||||
|
}}
|
||||||
|
;
|
||||||
|
|
||||||
|
base_interface:
|
||||||
|
#empty
|
||||||
|
|
|
||||||
|
':' identifier { $_[2] }
|
||||||
|
;
|
||||||
|
|
||||||
|
|
||||||
|
cpp_quote:
|
||||||
|
'cpp_quote' '(' text ')'
|
||||||
|
{{
|
||||||
|
"TYPE" => "CPP_QUOTE",
|
||||||
|
"DATA" => $_[3],
|
||||||
|
"FILE" => $_[0]->YYData->{FILE},
|
||||||
|
"LINE" => $_[0]->YYData->{LINE},
|
||||||
|
}}
|
||||||
|
;
|
||||||
|
|
||||||
|
definitions:
|
||||||
|
definition { [ $_[1] ] }
|
||||||
|
|
|
||||||
|
definitions definition { push(@{$_[1]}, $_[2]); $_[1] }
|
||||||
|
;
|
||||||
|
|
||||||
|
definition:
|
||||||
|
function
|
||||||
|
|
|
||||||
|
const
|
||||||
|
|
|
||||||
|
typedef
|
||||||
|
|
|
||||||
|
typedecl
|
||||||
|
|
|
||||||
|
cpp_quote
|
||||||
|
;
|
||||||
|
|
||||||
|
const:
|
||||||
|
'const' identifier pointers identifier '=' anytext ';'
|
||||||
|
{{
|
||||||
|
"TYPE" => "CONST",
|
||||||
|
"DTYPE" => $_[2],
|
||||||
|
"POINTERS" => $_[3],
|
||||||
|
"NAME" => $_[4],
|
||||||
|
"VALUE" => $_[6],
|
||||||
|
"FILE" => $_[0]->YYData->{FILE},
|
||||||
|
"LINE" => $_[0]->YYData->{LINE},
|
||||||
|
}}
|
||||||
|
|
|
||||||
|
'const' identifier pointers identifier array_len '=' anytext ';'
|
||||||
|
{{
|
||||||
|
"TYPE" => "CONST",
|
||||||
|
"DTYPE" => $_[2],
|
||||||
|
"POINTERS" => $_[3],
|
||||||
|
"NAME" => $_[4],
|
||||||
|
"ARRAY_LEN" => $_[5],
|
||||||
|
"VALUE" => $_[7],
|
||||||
|
"FILE" => $_[0]->YYData->{FILE},
|
||||||
|
"LINE" => $_[0]->YYData->{LINE},
|
||||||
|
}}
|
||||||
|
;
|
||||||
|
|
||||||
|
function:
|
||||||
|
property_list type identifier '(' element_list2 ')' ';'
|
||||||
|
{{
|
||||||
|
"TYPE" => "FUNCTION",
|
||||||
|
"NAME" => $_[3],
|
||||||
|
"RETURN_TYPE" => $_[2],
|
||||||
|
"PROPERTIES" => $_[1],
|
||||||
|
"ELEMENTS" => $_[5],
|
||||||
|
"FILE" => $_[0]->YYData->{FILE},
|
||||||
|
"LINE" => $_[0]->YYData->{LINE},
|
||||||
|
}}
|
||||||
|
;
|
||||||
|
|
||||||
|
typedef:
|
||||||
|
property_list 'typedef' optional_const type pointers identifier array_len ';'
|
||||||
|
{{
|
||||||
|
"TYPE" => "TYPEDEF",
|
||||||
|
"PROPERTIES" => $_[1],
|
||||||
|
"CONST" => $_[3],
|
||||||
|
"NAME" => $_[6],
|
||||||
|
"DATA" => $_[4],
|
||||||
|
"POINTERS" => $_[5],
|
||||||
|
"ARRAY_LEN" => $_[7],
|
||||||
|
"FILE" => $_[0]->YYData->{FILE},
|
||||||
|
"LINE" => $_[0]->YYData->{LINE},
|
||||||
|
}}
|
||||||
|
;
|
||||||
|
|
||||||
|
usertype:
|
||||||
|
struct
|
||||||
|
|
|
||||||
|
union
|
||||||
|
|
|
||||||
|
enum
|
||||||
|
|
|
||||||
|
bitmap
|
||||||
|
|
|
||||||
|
pipe
|
||||||
|
;
|
||||||
|
|
||||||
|
typedecl:
|
||||||
|
usertype ';' { $_[1] }
|
||||||
|
;
|
||||||
|
|
||||||
|
sign:
|
||||||
|
'signed'
|
||||||
|
|
|
||||||
|
'unsigned'
|
||||||
|
;
|
||||||
|
|
||||||
|
existingtype:
|
||||||
|
sign identifier { ($_[1]?$_[1]:"signed") ." $_[2]" }
|
||||||
|
|
|
||||||
|
identifier
|
||||||
|
;
|
||||||
|
|
||||||
|
type:
|
||||||
|
usertype
|
||||||
|
|
|
||||||
|
existingtype
|
||||||
|
|
|
||||||
|
void { "void" }
|
||||||
|
;
|
||||||
|
|
||||||
|
enum_body:
|
||||||
|
'{' enum_elements '}' { $_[2] }
|
||||||
|
;
|
||||||
|
|
||||||
|
opt_enum_body:
|
||||||
|
#empty
|
||||||
|
|
|
||||||
|
enum_body
|
||||||
|
;
|
||||||
|
|
||||||
|
enum:
|
||||||
|
property_list 'enum' optional_identifier opt_enum_body
|
||||||
|
{{
|
||||||
|
"TYPE" => "ENUM",
|
||||||
|
"PROPERTIES" => $_[1],
|
||||||
|
"NAME" => $_[3],
|
||||||
|
"ELEMENTS" => $_[4],
|
||||||
|
"FILE" => $_[0]->YYData->{FILE},
|
||||||
|
"LINE" => $_[0]->YYData->{LINE},
|
||||||
|
}}
|
||||||
|
;
|
||||||
|
|
||||||
|
enum_elements:
|
||||||
|
enum_element { [ $_[1] ] }
|
||||||
|
|
|
||||||
|
enum_elements ',' enum_element { push(@{$_[1]}, $_[3]); $_[1] }
|
||||||
|
;
|
||||||
|
|
||||||
|
enum_element:
|
||||||
|
identifier
|
||||||
|
|
|
||||||
|
identifier '=' anytext { "$_[1]$_[2]$_[3]" }
|
||||||
|
;
|
||||||
|
|
||||||
|
bitmap_body:
|
||||||
|
'{' opt_bitmap_elements '}' { $_[2] }
|
||||||
|
;
|
||||||
|
|
||||||
|
opt_bitmap_body:
|
||||||
|
#empty
|
||||||
|
|
|
||||||
|
bitmap_body
|
||||||
|
;
|
||||||
|
|
||||||
|
bitmap:
|
||||||
|
property_list 'bitmap' optional_identifier opt_bitmap_body
|
||||||
|
{{
|
||||||
|
"TYPE" => "BITMAP",
|
||||||
|
"PROPERTIES" => $_[1],
|
||||||
|
"NAME" => $_[3],
|
||||||
|
"ELEMENTS" => $_[4],
|
||||||
|
"FILE" => $_[0]->YYData->{FILE},
|
||||||
|
"LINE" => $_[0]->YYData->{LINE},
|
||||||
|
}}
|
||||||
|
;
|
||||||
|
|
||||||
|
bitmap_elements:
|
||||||
|
bitmap_element { [ $_[1] ] }
|
||||||
|
|
|
||||||
|
bitmap_elements ',' bitmap_element { push(@{$_[1]}, $_[3]); $_[1] }
|
||||||
|
;
|
||||||
|
|
||||||
|
opt_bitmap_elements:
|
||||||
|
#empty
|
||||||
|
|
|
||||||
|
bitmap_elements
|
||||||
|
;
|
||||||
|
|
||||||
|
bitmap_element:
|
||||||
|
identifier '=' anytext { "$_[1] ( $_[3] )" }
|
||||||
|
;
|
||||||
|
|
||||||
|
struct_body:
|
||||||
|
'{' element_list1 '}' { $_[2] }
|
||||||
|
;
|
||||||
|
|
||||||
|
opt_struct_body:
|
||||||
|
#empty
|
||||||
|
|
|
||||||
|
struct_body
|
||||||
|
;
|
||||||
|
|
||||||
|
struct:
|
||||||
|
property_list 'struct' optional_identifier opt_struct_body
|
||||||
|
{{
|
||||||
|
"TYPE" => "STRUCT",
|
||||||
|
"PROPERTIES" => $_[1],
|
||||||
|
"NAME" => $_[3],
|
||||||
|
"ELEMENTS" => $_[4],
|
||||||
|
"FILE" => $_[0]->YYData->{FILE},
|
||||||
|
"LINE" => $_[0]->YYData->{LINE},
|
||||||
|
}}
|
||||||
|
;
|
||||||
|
|
||||||
|
empty_element:
|
||||||
|
property_list ';'
|
||||||
|
{{
|
||||||
|
"NAME" => "",
|
||||||
|
"TYPE" => "EMPTY",
|
||||||
|
"PROPERTIES" => $_[1],
|
||||||
|
"POINTERS" => 0,
|
||||||
|
"ARRAY_LEN" => [],
|
||||||
|
"FILE" => $_[0]->YYData->{FILE},
|
||||||
|
"LINE" => $_[0]->YYData->{LINE},
|
||||||
|
}}
|
||||||
|
;
|
||||||
|
|
||||||
|
base_or_empty:
|
||||||
|
base_element ';'
|
||||||
|
|
|
||||||
|
empty_element;
|
||||||
|
|
||||||
|
optional_base_element:
|
||||||
|
property_list base_or_empty { $_[2]->{PROPERTIES} = FlattenHash([$_[1],$_[2]->{PROPERTIES}]); $_[2] }
|
||||||
|
;
|
||||||
|
|
||||||
|
union_elements:
|
||||||
|
#empty
|
||||||
|
|
|
||||||
|
union_elements optional_base_element { push(@{$_[1]}, $_[2]); $_[1] }
|
||||||
|
;
|
||||||
|
|
||||||
|
union_body:
|
||||||
|
'{' union_elements '}' { $_[2] }
|
||||||
|
;
|
||||||
|
|
||||||
|
opt_union_body:
|
||||||
|
#empty
|
||||||
|
|
|
||||||
|
union_body
|
||||||
|
;
|
||||||
|
|
||||||
|
union:
|
||||||
|
property_list 'union' optional_identifier opt_union_body
|
||||||
|
{{
|
||||||
|
"TYPE" => "UNION",
|
||||||
|
"PROPERTIES" => $_[1],
|
||||||
|
"NAME" => $_[3],
|
||||||
|
"ELEMENTS" => $_[4],
|
||||||
|
"FILE" => $_[0]->YYData->{FILE},
|
||||||
|
"LINE" => $_[0]->YYData->{LINE},
|
||||||
|
}}
|
||||||
|
;
|
||||||
|
|
||||||
|
base_element:
|
||||||
|
property_list type pointers identifier array_len
|
||||||
|
{{
|
||||||
|
"NAME" => $_[4],
|
||||||
|
"TYPE" => $_[2],
|
||||||
|
"PROPERTIES" => $_[1],
|
||||||
|
"POINTERS" => $_[3],
|
||||||
|
"ARRAY_LEN" => $_[5],
|
||||||
|
"FILE" => $_[0]->YYData->{FILE},
|
||||||
|
"LINE" => $_[0]->YYData->{LINE},
|
||||||
|
}}
|
||||||
|
;
|
||||||
|
|
||||||
|
pointers:
|
||||||
|
#empty
|
||||||
|
{ 0 }
|
||||||
|
|
|
||||||
|
pointers '*' { $_[1]+1 }
|
||||||
|
;
|
||||||
|
|
||||||
|
pipe:
|
||||||
|
property_list 'pipe' type
|
||||||
|
{{
|
||||||
|
"TYPE" => "PIPE",
|
||||||
|
"PROPERTIES" => $_[1],
|
||||||
|
"NAME" => undef,
|
||||||
|
"DATA" => {
|
||||||
|
"TYPE" => "STRUCT",
|
||||||
|
"PROPERTIES" => $_[1],
|
||||||
|
"NAME" => undef,
|
||||||
|
"ELEMENTS" => [{
|
||||||
|
"NAME" => "count",
|
||||||
|
"PROPERTIES" => $_[1],
|
||||||
|
"POINTERS" => 0,
|
||||||
|
"ARRAY_LEN" => [],
|
||||||
|
"TYPE" => "uint3264",
|
||||||
|
"FILE" => $_[0]->YYData->{FILE},
|
||||||
|
"LINE" => $_[0]->YYData->{LINE},
|
||||||
|
},{
|
||||||
|
"NAME" => "array",
|
||||||
|
"PROPERTIES" => $_[1],
|
||||||
|
"POINTERS" => 0,
|
||||||
|
"ARRAY_LEN" => [ "count" ],
|
||||||
|
"TYPE" => $_[3],
|
||||||
|
"FILE" => $_[0]->YYData->{FILE},
|
||||||
|
"LINE" => $_[0]->YYData->{LINE},
|
||||||
|
}],
|
||||||
|
"FILE" => $_[0]->YYData->{FILE},
|
||||||
|
"LINE" => $_[0]->YYData->{LINE},
|
||||||
|
},
|
||||||
|
"FILE" => $_[0]->YYData->{FILE},
|
||||||
|
"LINE" => $_[0]->YYData->{LINE},
|
||||||
|
}}
|
||||||
|
;
|
||||||
|
|
||||||
|
element_list1:
|
||||||
|
#empty
|
||||||
|
{ [] }
|
||||||
|
|
|
||||||
|
element_list1 base_element ';' { push(@{$_[1]}, $_[2]); $_[1] }
|
||||||
|
;
|
||||||
|
|
||||||
|
optional_const:
|
||||||
|
#empty { 0 }
|
||||||
|
|
|
||||||
|
'const' { 1 }
|
||||||
|
;
|
||||||
|
|
||||||
|
element_list2:
|
||||||
|
#empty
|
||||||
|
|
|
||||||
|
'void'
|
||||||
|
|
|
||||||
|
optional_const base_element { [ $_[2] ] }
|
||||||
|
|
|
||||||
|
element_list2 ',' optional_const base_element { push(@{$_[1]}, $_[4]); $_[1] }
|
||||||
|
;
|
||||||
|
|
||||||
|
array_len:
|
||||||
|
#empty { [] }
|
||||||
|
|
|
||||||
|
'[' ']' array_len { push(@{$_[3]}, "*"); $_[3] }
|
||||||
|
|
|
||||||
|
'[' anytext ']' array_len { push(@{$_[4]}, "$_[2]"); $_[4] }
|
||||||
|
;
|
||||||
|
|
||||||
|
property_list:
|
||||||
|
#empty
|
||||||
|
|
|
||||||
|
property_list '[' properties ']' { FlattenHash([$_[1],$_[3]]); }
|
||||||
|
;
|
||||||
|
|
||||||
|
properties:
|
||||||
|
property { $_[1] }
|
||||||
|
|
|
||||||
|
properties ',' property { FlattenHash([$_[1], $_[3]]); }
|
||||||
|
;
|
||||||
|
|
||||||
|
property:
|
||||||
|
identifier {{ "$_[1]" => "1" }}
|
||||||
|
|
|
||||||
|
identifier '(' commalisttext ')' {{ "$_[1]" => "$_[3]" }}
|
||||||
|
;
|
||||||
|
|
||||||
|
commalisttext:
|
||||||
|
anytext
|
||||||
|
|
|
||||||
|
commalisttext ',' anytext { "$_[1],$_[3]" }
|
||||||
|
;
|
||||||
|
|
||||||
|
anytext:
|
||||||
|
#empty
|
||||||
|
{ "" }
|
||||||
|
|
|
||||||
|
identifier
|
||||||
|
|
|
||||||
|
constant
|
||||||
|
|
|
||||||
|
text
|
||||||
|
|
|
||||||
|
anytext '-' anytext { "$_[1]$_[2]$_[3]" }
|
||||||
|
|
|
||||||
|
anytext '.' anytext { "$_[1]$_[2]$_[3]" }
|
||||||
|
|
|
||||||
|
anytext '*' anytext { "$_[1]$_[2]$_[3]" }
|
||||||
|
|
|
||||||
|
anytext '>' anytext { "$_[1]$_[2]$_[3]" }
|
||||||
|
|
|
||||||
|
anytext '<' anytext { "$_[1]$_[2]$_[3]" }
|
||||||
|
|
|
||||||
|
anytext '|' anytext { "$_[1]$_[2]$_[3]" }
|
||||||
|
|
|
||||||
|
anytext '&' anytext { "$_[1]$_[2]$_[3]" }
|
||||||
|
|
|
||||||
|
anytext '/' anytext { "$_[1]$_[2]$_[3]" }
|
||||||
|
|
|
||||||
|
anytext '?' anytext { "$_[1]$_[2]$_[3]" }
|
||||||
|
|
|
||||||
|
anytext ':' anytext { "$_[1]$_[2]$_[3]" }
|
||||||
|
|
|
||||||
|
anytext '=' anytext { "$_[1]$_[2]$_[3]" }
|
||||||
|
|
|
||||||
|
anytext '+' anytext { "$_[1]$_[2]$_[3]" }
|
||||||
|
|
|
||||||
|
anytext '~' anytext { "$_[1]$_[2]$_[3]" }
|
||||||
|
|
|
||||||
|
anytext '(' commalisttext ')' anytext { "$_[1]$_[2]$_[3]$_[4]$_[5]" }
|
||||||
|
|
|
||||||
|
anytext '{' commalisttext '}' anytext { "$_[1]$_[2]$_[3]$_[4]$_[5]" }
|
||||||
|
;
|
||||||
|
|
||||||
|
identifier:
|
||||||
|
IDENTIFIER
|
||||||
|
;
|
||||||
|
|
||||||
|
optional_identifier:
|
||||||
|
#empty { undef }
|
||||||
|
|
|
||||||
|
IDENTIFIER
|
||||||
|
;
|
||||||
|
|
||||||
|
constant:
|
||||||
|
CONSTANT
|
||||||
|
;
|
||||||
|
|
||||||
|
text:
|
||||||
|
TEXT { "\"$_[1]\"" }
|
||||||
|
;
|
||||||
|
|
||||||
|
optional_semicolon:
|
||||||
|
#empty
|
||||||
|
|
|
||||||
|
';'
|
||||||
|
;
|
||||||
|
|
||||||
|
|
||||||
|
#####################################
|
||||||
|
# start code
|
||||||
|
%%
|
||||||
|
|
||||||
|
use Parse::Pidl qw(error);
|
||||||
|
|
||||||
|
#####################################################################
|
||||||
|
# flatten an array of hashes into a single hash
|
||||||
|
sub FlattenHash($)
|
||||||
|
{
|
||||||
|
my $a = shift;
|
||||||
|
my %b;
|
||||||
|
for my $d (@{$a}) {
|
||||||
|
for my $k (keys %{$d}) {
|
||||||
|
$b{$k} = $d->{$k};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return \%b;
|
||||||
|
}
|
||||||
|
|
||||||
|
#####################################################################
|
||||||
|
# traverse a perl data structure removing any empty arrays or
|
||||||
|
# hashes and any hash elements that map to undef
|
||||||
|
sub CleanData($)
|
||||||
|
{
|
||||||
|
sub CleanData($);
|
||||||
|
my($v) = shift;
|
||||||
|
|
||||||
|
return undef if (not defined($v));
|
||||||
|
|
||||||
|
if (ref($v) eq "ARRAY") {
|
||||||
|
foreach my $i (0 .. $#{$v}) {
|
||||||
|
CleanData($v->[$i]);
|
||||||
|
}
|
||||||
|
# this removes any undefined elements from the array
|
||||||
|
@{$v} = grep { defined $_ } @{$v};
|
||||||
|
} elsif (ref($v) eq "HASH") {
|
||||||
|
foreach my $x (keys %{$v}) {
|
||||||
|
CleanData($v->{$x});
|
||||||
|
if (!defined $v->{$x}) {
|
||||||
|
delete($v->{$x});
|
||||||
|
next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $v;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub _Error {
|
||||||
|
if (exists $_[0]->YYData->{ERRMSG}) {
|
||||||
|
error($_[0]->YYData, $_[0]->YYData->{ERRMSG});
|
||||||
|
delete $_[0]->YYData->{ERRMSG};
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
my $last_token = $_[0]->YYData->{LAST_TOKEN};
|
||||||
|
|
||||||
|
error($_[0]->YYData, "Syntax error near '$last_token'");
|
||||||
|
}
|
||||||
|
|
||||||
|
sub _Lexer($)
|
||||||
|
{
|
||||||
|
my($parser)=shift;
|
||||||
|
|
||||||
|
$parser->YYData->{INPUT} or return('',undef);
|
||||||
|
|
||||||
|
again:
|
||||||
|
$parser->YYData->{INPUT} =~ s/^[ \t]*//;
|
||||||
|
|
||||||
|
for ($parser->YYData->{INPUT}) {
|
||||||
|
if (/^\#/) {
|
||||||
|
# Linemarker format is described at
|
||||||
|
# http://gcc.gnu.org/onlinedocs/cpp/Preprocessor-Output.html
|
||||||
|
if (s/^\# (\d+) \"(.*?)\"(( \d+){1,4}|)//) {
|
||||||
|
$parser->YYData->{LINE} = $1-1;
|
||||||
|
$parser->YYData->{FILE} = $2;
|
||||||
|
goto again;
|
||||||
|
}
|
||||||
|
if (s/^\#line (\d+) \"(.*?)\"( \d+|)//) {
|
||||||
|
$parser->YYData->{LINE} = $1-1;
|
||||||
|
$parser->YYData->{FILE} = $2;
|
||||||
|
goto again;
|
||||||
|
}
|
||||||
|
if (s/^(\#.*)$//m) {
|
||||||
|
goto again;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (s/^(\n)//) {
|
||||||
|
$parser->YYData->{LINE}++;
|
||||||
|
goto again;
|
||||||
|
}
|
||||||
|
if (s/^\"(.*?)\"//) {
|
||||||
|
$parser->YYData->{LAST_TOKEN} = $1;
|
||||||
|
return('TEXT',$1);
|
||||||
|
}
|
||||||
|
if (s/^(\d+)(\W|$)/$2/) {
|
||||||
|
$parser->YYData->{LAST_TOKEN} = $1;
|
||||||
|
return('CONSTANT',$1);
|
||||||
|
}
|
||||||
|
if (s/^([\w_]+)//) {
|
||||||
|
$parser->YYData->{LAST_TOKEN} = $1;
|
||||||
|
if ($1 =~
|
||||||
|
/^(coclass|interface|import|importlib
|
||||||
|
|include|cpp_quote|typedef
|
||||||
|
|union|struct|enum|bitmap|pipe
|
||||||
|
|void|const|unsigned|signed)$/x) {
|
||||||
|
return $1;
|
||||||
|
}
|
||||||
|
return('IDENTIFIER',$1);
|
||||||
|
}
|
||||||
|
if (s/^(.)//s) {
|
||||||
|
$parser->YYData->{LAST_TOKEN} = $1;
|
||||||
|
return($1,$1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sub parse_string
|
||||||
|
{
|
||||||
|
my ($data,$filename) = @_;
|
||||||
|
|
||||||
|
my $self = new Parse::Pidl::IDL;
|
||||||
|
|
||||||
|
$self->YYData->{FILE} = $filename;
|
||||||
|
$self->YYData->{INPUT} = $data;
|
||||||
|
$self->YYData->{LINE} = 0;
|
||||||
|
$self->YYData->{LAST_TOKEN} = "NONE";
|
||||||
|
|
||||||
|
my $idl = $self->YYParse( yylex => \&_Lexer, yyerror => \&_Error );
|
||||||
|
|
||||||
|
return CleanData($idl);
|
||||||
|
}
|
||||||
|
|
||||||
|
sub parse_file($$)
|
||||||
|
{
|
||||||
|
my ($filename,$incdirs) = @_;
|
||||||
|
|
||||||
|
my $saved_delim = $/;
|
||||||
|
undef $/;
|
||||||
|
my $cpp = $ENV{CPP};
|
||||||
|
my $options = "";
|
||||||
|
if (! defined $cpp) {
|
||||||
|
if (defined $ENV{CC}) {
|
||||||
|
$cpp = "$ENV{CC}";
|
||||||
|
$options = "-E";
|
||||||
|
} else {
|
||||||
|
$cpp = "cpp";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
my $includes = join('',map { " -I$_" } @$incdirs);
|
||||||
|
my $data = `$cpp $options -D__PIDL__$includes -xc "$filename"`;
|
||||||
|
$/ = $saved_delim;
|
||||||
|
|
||||||
|
return parse_string($data, $filename);
|
||||||
|
}
|
44
tools/pidl/lib/Parse/Pidl.pm
Normal file
44
tools/pidl/lib/Parse/Pidl.pm
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
###################################################
|
||||||
|
# package to parse IDL files and generate code for
|
||||||
|
# rpc functions in Samba
|
||||||
|
# Copyright tridge@samba.org 2000-2003
|
||||||
|
# Copyright jelmer@samba.org 2005
|
||||||
|
# released under the GNU GPL
|
||||||
|
|
||||||
|
package Parse::Pidl;
|
||||||
|
|
||||||
|
require Exporter;
|
||||||
|
@ISA = qw(Exporter);
|
||||||
|
@EXPORT_OK = qw(warning error fatal $VERSION);
|
||||||
|
|
||||||
|
use strict;
|
||||||
|
|
||||||
|
use vars qw ( $VERSION );
|
||||||
|
|
||||||
|
$VERSION = '0.02';
|
||||||
|
|
||||||
|
sub warning
|
||||||
|
{
|
||||||
|
my ($l,$m) = @_;
|
||||||
|
if ($l) {
|
||||||
|
print STDERR "$l->{FILE}:$l->{LINE}: ";
|
||||||
|
}
|
||||||
|
print STDERR "warning: $m\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
sub error
|
||||||
|
{
|
||||||
|
my ($l,$m) = @_;
|
||||||
|
if ($l) {
|
||||||
|
print STDERR "$l->{FILE}:$l->{LINE}: ";
|
||||||
|
}
|
||||||
|
print STDERR "error: $m\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
sub fatal($$)
|
||||||
|
{
|
||||||
|
my ($e,$s) = @_;
|
||||||
|
die("$e->{FILE}:$e->{LINE}: $s\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
1;
|
319
tools/pidl/lib/Parse/Pidl/COMROGUE/Header.pm
Normal file
319
tools/pidl/lib/Parse/Pidl/COMROGUE/Header.pm
Normal file
|
@ -0,0 +1,319 @@
|
||||||
|
# COM Header generation
|
||||||
|
# (C) 2005 Jelmer Vernooij <jelmer@samba.org>
|
||||||
|
# Modifications (C) 2013 Eric J. Bowersox <erbo@erbosoft.com>
|
||||||
|
|
||||||
|
package Parse::Pidl::COMROGUE::Header;
|
||||||
|
|
||||||
|
use Parse::Pidl::Typelist qw(mapTypeName maybeMapScalarType is_struct);
|
||||||
|
use Parse::Pidl::Util qw(has_property is_constant);
|
||||||
|
|
||||||
|
use vars qw($VERSION);
|
||||||
|
$VERSION = '0.01';
|
||||||
|
|
||||||
|
use strict;
|
||||||
|
|
||||||
|
sub stripquotes($)
|
||||||
|
{
|
||||||
|
my $str = shift;
|
||||||
|
$str =~ s/^\"//;
|
||||||
|
$str =~ s/\"$//;
|
||||||
|
return $str;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub GetArgumentProtoList($)
|
||||||
|
{
|
||||||
|
my $f = shift;
|
||||||
|
my $res = "";
|
||||||
|
my $first = 1;
|
||||||
|
|
||||||
|
foreach my $a (@{$f->{ELEMENTS}}) {
|
||||||
|
$res .= ", " unless $first;
|
||||||
|
$first = 0;
|
||||||
|
$res .= maybeMapScalarType($a->{TYPE}) . " ";
|
||||||
|
|
||||||
|
my $l = $a->{POINTERS};
|
||||||
|
$l-- if (Parse::Pidl::Typelist::scalar_is_reference($a->{TYPE}));
|
||||||
|
foreach my $i (1..$l) {
|
||||||
|
$res .= "*";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (defined $a->{ARRAY_LEN}[0] && !is_constant($a->{ARRAY_LEN}[0]) &&
|
||||||
|
!$a->{POINTERS}) {
|
||||||
|
$res .= "*";
|
||||||
|
}
|
||||||
|
$res .= $a->{NAME};
|
||||||
|
if (defined $a->{ARRAY_LEN}[0] && is_constant($a->{ARRAY_LEN}[0])) {
|
||||||
|
$res .= "[$a->{ARRAY_LEN}[0]]";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return undef if $first;
|
||||||
|
return $res;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub GetArgumentList($)
|
||||||
|
{
|
||||||
|
my $f = shift;
|
||||||
|
my $res = "";
|
||||||
|
my $first = 1;
|
||||||
|
|
||||||
|
foreach (@{$f->{ELEMENTS}}) {
|
||||||
|
$res .= ", " unless $first;
|
||||||
|
$first = 0;
|
||||||
|
$res .= "$_->{NAME}";
|
||||||
|
}
|
||||||
|
|
||||||
|
return undef if $first;
|
||||||
|
return $res;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub MethodsDefinition($)
|
||||||
|
{
|
||||||
|
my $interface = shift;
|
||||||
|
my $res = "";
|
||||||
|
|
||||||
|
$res .= "#define METHODS_" . $interface->{NAME} . " \\\n";
|
||||||
|
if (defined($interface->{BASE})) {
|
||||||
|
$res .= "\tINHERIT_METHODS(METHODS_" . $interface->{BASE} . ") \\\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
my $data = $interface->{DATA};
|
||||||
|
foreach my $d (@{$data}) {
|
||||||
|
next unless ($d->{TYPE} eq "FUNCTION");
|
||||||
|
if ($d->{RETURN_TYPE} eq "HRESULT") {
|
||||||
|
$res .= "\tSTDMETHOD($d->{NAME})";
|
||||||
|
} else {
|
||||||
|
$res .= "\tSTDMETHOD_($d->{NAME}," . $d->{RETURN_TYPE} . ")";
|
||||||
|
}
|
||||||
|
my $args = GetArgumentProtoList($d);
|
||||||
|
if (defined($args)) {
|
||||||
|
$res .= "(THIS_($interface->{NAME}) $args) PURE;\\\n";
|
||||||
|
} else {
|
||||||
|
$res .= "(THIS($interface->{NAME})) PURE;\\\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$res .= "\tEND_METHODS\n\n";
|
||||||
|
return $res;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub MakeGUIDDef($$$)
|
||||||
|
{
|
||||||
|
my $t = shift;
|
||||||
|
my $name = shift;
|
||||||
|
my $uuid = shift;
|
||||||
|
|
||||||
|
my @uuidparts = split(/-/, $uuid);
|
||||||
|
my $b1 = substr($uuidparts[3], 0, 2);
|
||||||
|
my $b2 = substr($uuidparts[3], 2, 2);
|
||||||
|
my $b3 = substr($uuidparts[4], 0, 2);
|
||||||
|
my $b4 = substr($uuidparts[4], 2, 2);
|
||||||
|
my $b5 = substr($uuidparts[4], 4, 2);
|
||||||
|
my $b6 = substr($uuidparts[4], 6, 2);
|
||||||
|
my $b7 = substr($uuidparts[4], 8, 2);
|
||||||
|
my $b8 = substr($uuidparts[4], 10, 2);
|
||||||
|
|
||||||
|
return "DEFINE_$t(${t}_$name, 0x$uuidparts[0], 0x$uuidparts[1], 0x$uuidparts[2], " .
|
||||||
|
"0x$b1, 0x$b2, 0x$b3, 0x$b4, 0x$b5, 0x$b6, 0x$b7, 0x$b8);\n\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
sub ParseImports($)
|
||||||
|
{
|
||||||
|
my $imp = shift;
|
||||||
|
my $res = "";
|
||||||
|
my $seen = 0;
|
||||||
|
|
||||||
|
foreach my $p (@{$imp->{PATHS}}) {
|
||||||
|
my $header = $p;
|
||||||
|
$header =~ s/\.idl/\.h/;
|
||||||
|
$header =~ s/^\"/</;
|
||||||
|
$header =~ s/\"$/>/;
|
||||||
|
$res .= "#include $header\n";
|
||||||
|
$seen = 1;
|
||||||
|
}
|
||||||
|
$res .= "\n" if $seen;
|
||||||
|
return $res;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub ParseElement($$)
|
||||||
|
{
|
||||||
|
my $prefix = shift;
|
||||||
|
my $element = shift;
|
||||||
|
my $res = "";
|
||||||
|
|
||||||
|
$res .= $prefix . maybeMapScalarType($element->{TYPE}) . " " . $element->{NAME};
|
||||||
|
if (defined($element->{ARRAY_LEN})) {
|
||||||
|
foreach my $l (@{$element->{ARRAY_LEN}}) {
|
||||||
|
$res .= "[" . $l . "]";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$res .= ";\n";
|
||||||
|
return $res;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub ParseTypedef($)
|
||||||
|
{
|
||||||
|
my $def = shift;
|
||||||
|
my $res = "";
|
||||||
|
|
||||||
|
$res .= "typedef ";
|
||||||
|
$res .= "const " if ($def->{CONST});
|
||||||
|
if (ref($def->{DATA}) ne "HASH") {
|
||||||
|
$res .= maybeMapScalarType($def->{DATA}) . " ";
|
||||||
|
} else {
|
||||||
|
if (is_struct($def->{DATA})) {
|
||||||
|
$res .= mapTypeName($def->{DATA}) . " {\n";
|
||||||
|
foreach my $elt (@{$def->{DATA}->{ELEMENTS}}) {
|
||||||
|
$res .= ParseElement("\t", $elt);
|
||||||
|
}
|
||||||
|
$res .= "} ";
|
||||||
|
} else {
|
||||||
|
$res .= mapTypeName($def->{DATA}) . " ";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
my $l = $def->{POINTERS};
|
||||||
|
$l-- if (Parse::Pidl::Typelist::scalar_is_reference($def->{TYPE}));
|
||||||
|
foreach my $i (1..$l) {
|
||||||
|
$res .= "*";
|
||||||
|
}
|
||||||
|
$res .= $def->{NAME} . ";\n";
|
||||||
|
return $res;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub ParseTypedefs($)
|
||||||
|
{
|
||||||
|
my $if = shift;
|
||||||
|
my $res = "";
|
||||||
|
my $count = 0;
|
||||||
|
|
||||||
|
foreach my $d (@{$if->{DATA}}) {
|
||||||
|
$res .= stripquotes($d->{DATA}) . "\n" if ($d->{TYPE} eq "CPP_QUOTE");
|
||||||
|
next unless ($d->{TYPE} eq "TYPEDEF");
|
||||||
|
++$count;
|
||||||
|
$res .= ParseTypedef($d);
|
||||||
|
}
|
||||||
|
|
||||||
|
$res .= "\n";
|
||||||
|
return "" if ($count == 0);
|
||||||
|
return $res;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub ParseInterface($)
|
||||||
|
{
|
||||||
|
my $if = shift;
|
||||||
|
my $res;
|
||||||
|
my $d;
|
||||||
|
|
||||||
|
$res .= "/*---------------------------------------------------------------\n";
|
||||||
|
$res .= " * Interface $if->{NAME}\n";
|
||||||
|
$res .= " *---------------------------------------------------------------\n";
|
||||||
|
$res .= " */\n\n";
|
||||||
|
|
||||||
|
$res .= MakeGUIDDef("IID", $if->{NAME}, $if->{PROPERTIES}->{uuid});
|
||||||
|
|
||||||
|
$res .= MethodsDefinition($if);
|
||||||
|
|
||||||
|
if (defined($if->{BASE})) {
|
||||||
|
$res .= "BEGIN_INTERFACE_(" . $if->{NAME} . ", " . $if->{BASE} . ")\n";
|
||||||
|
} else {
|
||||||
|
$res .= "BEGIN_INTERFACE(" . $if->{NAME} . ")\n";
|
||||||
|
}
|
||||||
|
$res .= "\tMETHODS_" . $if->{NAME} . "\n";
|
||||||
|
$res .= "END_INTERFACE(" . $if->{NAME} . ")\n\n";
|
||||||
|
|
||||||
|
foreach $d (@{$if->{DATA}}) {
|
||||||
|
$res .= stripquotes($d->{DATA}) . "\n" if ($d->{TYPE} eq "CPP_QUOTE");
|
||||||
|
$res .= ParseTypedef($d) if ($d->{TYPE} eq "TYPEDEF");
|
||||||
|
}
|
||||||
|
|
||||||
|
$res .= "\n#ifdef CINTERFACE\n\n";
|
||||||
|
|
||||||
|
foreach $d (@{$if->{DATA}}) {
|
||||||
|
next unless ($d->{TYPE} eq "FUNCTION");
|
||||||
|
my $args = GetArgumentList($d);
|
||||||
|
if (defined($args)) {
|
||||||
|
$res .= "#define $if->{NAME}_$d->{NAME}(pInterface, $args) \\\n";
|
||||||
|
$res .= "\t(*((pInterface)->pVTable->$d->{NAME}))(pInterface, $args)\n";
|
||||||
|
} else {
|
||||||
|
$res .= "#define $if->{NAME}_$d->{NAME}(pInterface) \\\n";
|
||||||
|
$res .= "\t(*((pInterface)->pVTable->$d->{NAME}))(pInterface)\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$res .= "\n#endif /* CINTERFACE */\n\n";
|
||||||
|
return $res;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub ParseCoClass($)
|
||||||
|
{
|
||||||
|
my ($c) = @_;
|
||||||
|
my $res = "";
|
||||||
|
|
||||||
|
$res .= "/*---------------------------------------------------------------\n";
|
||||||
|
$res .= " * Class $c->{NAME}\n";
|
||||||
|
$res .= " *---------------------------------------------------------------\n";
|
||||||
|
$res .= " */\n\n";
|
||||||
|
|
||||||
|
$res .= MakeGUIDDef("CLSID", $c->{NAME}, $c->{PROPERTIES}->{uuid});
|
||||||
|
|
||||||
|
if (has_property($c, "progid")) {
|
||||||
|
$res .= "#define PROGID_" . $c->{NAME} . " \"$c->{PROPERTIES}->{progid}\"\n";
|
||||||
|
}
|
||||||
|
$res .= "\n";
|
||||||
|
return $res;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub Parse($$$)
|
||||||
|
{
|
||||||
|
my ($idl,$basename, $srcfile) = @_;
|
||||||
|
my $res = "";
|
||||||
|
my $has_obj = 0;
|
||||||
|
|
||||||
|
$res .= "/* COMROGUE: Autogenerated from IDL file $srcfile */\n\n";
|
||||||
|
|
||||||
|
my $include_sym = "__" . uc($basename) . "_H_INCLUDED";
|
||||||
|
|
||||||
|
$res .= "#ifndef $include_sym\n" .
|
||||||
|
"#define $include_sym\n\n" .
|
||||||
|
"#ifndef __ASM__\n\n";
|
||||||
|
my $want_macro_headers = 1;
|
||||||
|
|
||||||
|
foreach (@{$idl})
|
||||||
|
{
|
||||||
|
if ($_->{TYPE} eq "CPP_QUOTE") {
|
||||||
|
$res .= stripquotes($_->{DATA}) . "\n";
|
||||||
|
}
|
||||||
|
if ($_->{TYPE} eq "IMPORT") {
|
||||||
|
$res .= ParseImports($_);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($_->{TYPE} eq "INTERFACE") {
|
||||||
|
if (has_property($_, "object")) {
|
||||||
|
if ($want_macro_headers) {
|
||||||
|
$res .= "#include <comrogue/object_definition_macros.h>\n\n";
|
||||||
|
$want_macro_headers = 0;
|
||||||
|
}
|
||||||
|
$res .= ParseInterface($_);
|
||||||
|
} else {
|
||||||
|
$res .= ParseTypedefs($_);
|
||||||
|
}
|
||||||
|
$has_obj = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($_->{TYPE} eq "COCLASS") {
|
||||||
|
if ($want_macro_headers) {
|
||||||
|
$res .= "#include <comrogue/object_definition_macros.h>\n\n";
|
||||||
|
$want_macro_headers = 0;
|
||||||
|
}
|
||||||
|
$res.=ParseCoClass($_);
|
||||||
|
$has_obj = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$res .= "#endif /* __ASM__ */\n\n";
|
||||||
|
$res .= "#endif /* $include_sym */\n";
|
||||||
|
|
||||||
|
return $res if ($has_obj);
|
||||||
|
return undef;
|
||||||
|
}
|
||||||
|
|
||||||
|
1;
|
52
tools/pidl/lib/Parse/Pidl/CUtil.pm
Normal file
52
tools/pidl/lib/Parse/Pidl/CUtil.pm
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
###################################################
|
||||||
|
# C utility functions for pidl
|
||||||
|
# Copyright jelmer@samba.org 2005-2007
|
||||||
|
# released under the GNU GPL
|
||||||
|
package Parse::Pidl::CUtil;
|
||||||
|
|
||||||
|
require Exporter;
|
||||||
|
@ISA = qw(Exporter);
|
||||||
|
@EXPORT = qw(get_pointer_to get_value_of get_array_element);
|
||||||
|
use vars qw($VERSION);
|
||||||
|
$VERSION = '0.01';
|
||||||
|
|
||||||
|
use strict;
|
||||||
|
|
||||||
|
sub get_pointer_to($)
|
||||||
|
{
|
||||||
|
my $var_name = shift;
|
||||||
|
|
||||||
|
if ($var_name =~ /^\*(.*)$/) {
|
||||||
|
return $1;
|
||||||
|
} elsif ($var_name =~ /^\&(.*)$/) {
|
||||||
|
return "&($var_name)";
|
||||||
|
} else {
|
||||||
|
return "&$var_name";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sub get_value_of($)
|
||||||
|
{
|
||||||
|
my $var_name = shift;
|
||||||
|
|
||||||
|
if ($var_name =~ /^\&(.*)$/) {
|
||||||
|
return $1;
|
||||||
|
} else {
|
||||||
|
return "*$var_name";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sub get_array_element($$)
|
||||||
|
{
|
||||||
|
my ($var_name, $idx) = @_;
|
||||||
|
|
||||||
|
if ($var_name =~ /^\*.*$/) {
|
||||||
|
$var_name = "($var_name)";
|
||||||
|
} elsif ($var_name =~ /^\&.*$/) {
|
||||||
|
$var_name = "($var_name)";
|
||||||
|
}
|
||||||
|
|
||||||
|
return "$var_name"."[$idx]";
|
||||||
|
}
|
||||||
|
|
||||||
|
1;
|
168
tools/pidl/lib/Parse/Pidl/Compat.pm
Normal file
168
tools/pidl/lib/Parse/Pidl/Compat.pm
Normal file
|
@ -0,0 +1,168 @@
|
||||||
|
###################################################
|
||||||
|
# IDL Compatibility checker
|
||||||
|
# Copyright jelmer@samba.org 2005
|
||||||
|
# released under the GNU GPL
|
||||||
|
|
||||||
|
package Parse::Pidl::Compat;
|
||||||
|
|
||||||
|
use Parse::Pidl qw(warning);
|
||||||
|
use Parse::Pidl::Util qw(has_property);
|
||||||
|
use strict;
|
||||||
|
|
||||||
|
use vars qw($VERSION);
|
||||||
|
$VERSION = '0.01';
|
||||||
|
|
||||||
|
my %supported_properties = (
|
||||||
|
# interface
|
||||||
|
"helpstring" => ["INTERFACE", "FUNCTION"],
|
||||||
|
"version" => ["INTERFACE"],
|
||||||
|
"uuid" => ["INTERFACE"],
|
||||||
|
"endpoint" => ["INTERFACE"],
|
||||||
|
"pointer_default" => ["INTERFACE"],
|
||||||
|
"no_srv_register" => ["INTERFACE"],
|
||||||
|
|
||||||
|
# dcom
|
||||||
|
"object" => ["INTERFACE"],
|
||||||
|
"local" => ["INTERFACE", "FUNCTION"],
|
||||||
|
"iid_is" => ["ELEMENT"],
|
||||||
|
"call_as" => ["FUNCTION"],
|
||||||
|
"idempotent" => ["FUNCTION"],
|
||||||
|
|
||||||
|
# function
|
||||||
|
"in" => ["ELEMENT"],
|
||||||
|
"out" => ["ELEMENT"],
|
||||||
|
|
||||||
|
# pointer
|
||||||
|
"ref" => ["ELEMENT"],
|
||||||
|
"ptr" => ["ELEMENT"],
|
||||||
|
"unique" => ["ELEMENT"],
|
||||||
|
"ignore" => ["ELEMENT"],
|
||||||
|
|
||||||
|
"value" => ["ELEMENT"],
|
||||||
|
|
||||||
|
# generic
|
||||||
|
"public" => ["FUNCTION", "TYPEDEF"],
|
||||||
|
"nopush" => ["FUNCTION", "TYPEDEF"],
|
||||||
|
"nopull" => ["FUNCTION", "TYPEDEF"],
|
||||||
|
"noprint" => ["FUNCTION", "TYPEDEF"],
|
||||||
|
"nopython" => ["FUNCTION", "TYPEDEF"],
|
||||||
|
|
||||||
|
# union
|
||||||
|
"switch_is" => ["ELEMENT"],
|
||||||
|
"switch_type" => ["ELEMENT", "TYPEDEF"],
|
||||||
|
"case" => ["ELEMENT"],
|
||||||
|
"default" => ["ELEMENT"],
|
||||||
|
|
||||||
|
# subcontext
|
||||||
|
"subcontext" => ["ELEMENT"],
|
||||||
|
"subcontext_size" => ["ELEMENT"],
|
||||||
|
|
||||||
|
# enum
|
||||||
|
"enum16bit" => ["TYPEDEF"],
|
||||||
|
"v1_enum" => ["TYPEDEF"],
|
||||||
|
|
||||||
|
# bitmap
|
||||||
|
"bitmap8bit" => ["TYPEDEF"],
|
||||||
|
"bitmap16bit" => ["TYPEDEF"],
|
||||||
|
"bitmap32bit" => ["TYPEDEF"],
|
||||||
|
"bitmap64bit" => ["TYPEDEF"],
|
||||||
|
|
||||||
|
# array
|
||||||
|
"range" => ["ELEMENT"],
|
||||||
|
"size_is" => ["ELEMENT"],
|
||||||
|
"string" => ["ELEMENT"],
|
||||||
|
"noheader" => ["ELEMENT"],
|
||||||
|
"charset" => ["ELEMENT"],
|
||||||
|
"length_is" => ["ELEMENT"],
|
||||||
|
);
|
||||||
|
|
||||||
|
sub CheckTypedef($)
|
||||||
|
{
|
||||||
|
my ($td) = @_;
|
||||||
|
|
||||||
|
if (has_property($td, "nodiscriminant")) {
|
||||||
|
warning($td, "nodiscriminant property not supported");
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($td->{TYPE} eq "BITMAP") {
|
||||||
|
warning($td, "converting bitmap to scalar");
|
||||||
|
#FIXME
|
||||||
|
}
|
||||||
|
|
||||||
|
if (has_property($td, "gensize")) {
|
||||||
|
warning($td, "ignoring gensize() property. ");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (has_property($td, "enum8bit") and has_property($td, "enum16bit")) {
|
||||||
|
warning($td, "8 and 16 bit enums not supported, converting to scalar");
|
||||||
|
#FIXME
|
||||||
|
}
|
||||||
|
|
||||||
|
StripProperties($td);
|
||||||
|
}
|
||||||
|
|
||||||
|
sub CheckElement($)
|
||||||
|
{
|
||||||
|
my $e = shift;
|
||||||
|
|
||||||
|
if (has_property($e, "noheader")) {
|
||||||
|
warning($e, "noheader property not supported");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (has_property($e, "subcontext")) {
|
||||||
|
warning($e, "converting subcontext to byte array");
|
||||||
|
#FIXME
|
||||||
|
}
|
||||||
|
|
||||||
|
if (has_property($e, "compression")) {
|
||||||
|
warning($e, "compression() property not supported");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (has_property($e, "sptr")) {
|
||||||
|
warning($e, "sptr() pointer property not supported");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (has_property($e, "relative")) {
|
||||||
|
warning($e, "relative() pointer property not supported");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (has_property($e, "relative_short")) {
|
||||||
|
warning($e, "relative_short() pointer property not supported");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (has_property($e, "flag")) {
|
||||||
|
warning($e, "ignoring flag() property");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (has_property($e, "value")) {
|
||||||
|
warning($e, "ignoring value() property");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sub CheckFunction($)
|
||||||
|
{
|
||||||
|
my $fn = shift;
|
||||||
|
|
||||||
|
if (has_property($fn, "noopnum")) {
|
||||||
|
warning($fn, "noopnum not converted. Opcodes will be out of sync.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sub CheckInterface($)
|
||||||
|
{
|
||||||
|
my $if = shift;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
sub Check($)
|
||||||
|
{
|
||||||
|
my $pidl = shift;
|
||||||
|
my $nidl = [];
|
||||||
|
|
||||||
|
foreach (@{$pidl}) {
|
||||||
|
push (@$nidl, CheckInterface($_)) if ($_->{TYPE} eq "INTERFACE");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
1;
|
294
tools/pidl/lib/Parse/Pidl/Dump.pm
Normal file
294
tools/pidl/lib/Parse/Pidl/Dump.pm
Normal file
|
@ -0,0 +1,294 @@
|
||||||
|
###################################################
|
||||||
|
# dump function for IDL structures
|
||||||
|
# Copyright tridge@samba.org 2000
|
||||||
|
# Copyright jelmer@samba.org 2005
|
||||||
|
# released under the GNU GPL
|
||||||
|
|
||||||
|
=pod
|
||||||
|
|
||||||
|
=head1 NAME
|
||||||
|
|
||||||
|
Parse::Pidl::Dump - Dump support
|
||||||
|
|
||||||
|
=head1 DESCRIPTION
|
||||||
|
|
||||||
|
This module provides functions that can generate IDL code from
|
||||||
|
internal pidl data structures.
|
||||||
|
|
||||||
|
=cut
|
||||||
|
|
||||||
|
package Parse::Pidl::Dump;
|
||||||
|
|
||||||
|
use Exporter;
|
||||||
|
|
||||||
|
use vars qw($VERSION);
|
||||||
|
$VERSION = '0.01';
|
||||||
|
@ISA = qw(Exporter);
|
||||||
|
@EXPORT_OK = qw(DumpType DumpTypedef DumpStruct DumpEnum DumpBitmap DumpUnion DumpFunction);
|
||||||
|
|
||||||
|
use strict;
|
||||||
|
use Parse::Pidl::Util qw(has_property);
|
||||||
|
|
||||||
|
my($res);
|
||||||
|
|
||||||
|
#####################################################################
|
||||||
|
# dump a properties list
|
||||||
|
sub DumpProperties($)
|
||||||
|
{
|
||||||
|
my($props) = shift;
|
||||||
|
my $res = "";
|
||||||
|
|
||||||
|
foreach my $d ($props) {
|
||||||
|
foreach my $k (keys %{$d}) {
|
||||||
|
if ($k eq "in") {
|
||||||
|
$res .= "[in] ";
|
||||||
|
next;
|
||||||
|
}
|
||||||
|
if ($k eq "out") {
|
||||||
|
$res .= "[out] ";
|
||||||
|
next;
|
||||||
|
}
|
||||||
|
if ($k eq "ref") {
|
||||||
|
$res .= "[ref] ";
|
||||||
|
next;
|
||||||
|
}
|
||||||
|
$res .= "[$k($d->{$k})] ";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $res;
|
||||||
|
}
|
||||||
|
|
||||||
|
#####################################################################
|
||||||
|
# dump a structure element
|
||||||
|
sub DumpElement($)
|
||||||
|
{
|
||||||
|
my($element) = shift;
|
||||||
|
my $res = "";
|
||||||
|
|
||||||
|
(defined $element->{PROPERTIES}) &&
|
||||||
|
($res .= DumpProperties($element->{PROPERTIES}));
|
||||||
|
$res .= DumpType($element->{TYPE});
|
||||||
|
$res .= " ";
|
||||||
|
for my $i (1..$element->{POINTERS}) {
|
||||||
|
$res .= "*";
|
||||||
|
}
|
||||||
|
$res .= "$element->{NAME}";
|
||||||
|
foreach (@{$element->{ARRAY_LEN}}) {
|
||||||
|
$res .= "[$_]";
|
||||||
|
}
|
||||||
|
|
||||||
|
return $res;
|
||||||
|
}
|
||||||
|
|
||||||
|
#####################################################################
|
||||||
|
# dump a struct
|
||||||
|
sub DumpStruct($)
|
||||||
|
{
|
||||||
|
my($struct) = shift;
|
||||||
|
my($res);
|
||||||
|
|
||||||
|
$res .= "struct ";
|
||||||
|
if ($struct->{NAME}) {
|
||||||
|
$res.="$struct->{NAME} ";
|
||||||
|
}
|
||||||
|
|
||||||
|
$res.="{\n";
|
||||||
|
if (defined $struct->{ELEMENTS}) {
|
||||||
|
foreach (@{$struct->{ELEMENTS}}) {
|
||||||
|
$res .= "\t" . DumpElement($_) . ";\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$res .= "}";
|
||||||
|
|
||||||
|
return $res;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#####################################################################
|
||||||
|
# dump a struct
|
||||||
|
sub DumpEnum($)
|
||||||
|
{
|
||||||
|
my($enum) = shift;
|
||||||
|
my($res);
|
||||||
|
|
||||||
|
$res .= "enum {\n";
|
||||||
|
|
||||||
|
foreach (@{$enum->{ELEMENTS}}) {
|
||||||
|
if (/^([A-Za-z0-9_]+)[ \t]*\((.*)\)$/) {
|
||||||
|
$res .= "\t$1 = $2,\n";
|
||||||
|
} else {
|
||||||
|
$res .= "\t$_,\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$res.= "}";
|
||||||
|
|
||||||
|
return $res;
|
||||||
|
}
|
||||||
|
|
||||||
|
#####################################################################
|
||||||
|
# dump a struct
|
||||||
|
sub DumpBitmap($)
|
||||||
|
{
|
||||||
|
my($bitmap) = shift;
|
||||||
|
my($res);
|
||||||
|
|
||||||
|
$res .= "bitmap {\n";
|
||||||
|
|
||||||
|
foreach (@{$bitmap->{ELEMENTS}}) {
|
||||||
|
if (/^([A-Za-z0-9_]+)[ \t]*\((.*)\)$/) {
|
||||||
|
$res .= "\t$1 = $2,\n";
|
||||||
|
} else {
|
||||||
|
die ("Bitmap $bitmap->{NAME} has field $_ without proper value");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$res.= "}";
|
||||||
|
|
||||||
|
return $res;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#####################################################################
|
||||||
|
# dump a union element
|
||||||
|
sub DumpUnionElement($)
|
||||||
|
{
|
||||||
|
my($element) = shift;
|
||||||
|
my($res);
|
||||||
|
|
||||||
|
if (has_property($element, "default")) {
|
||||||
|
$res .= "[default] ;\n";
|
||||||
|
} else {
|
||||||
|
$res .= "[case($element->{PROPERTIES}->{case})] ";
|
||||||
|
$res .= DumpElement($element), if defined($element);
|
||||||
|
$res .= ";\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
return $res;
|
||||||
|
}
|
||||||
|
|
||||||
|
#####################################################################
|
||||||
|
# dump a union
|
||||||
|
sub DumpUnion($)
|
||||||
|
{
|
||||||
|
my($union) = shift;
|
||||||
|
my($res);
|
||||||
|
|
||||||
|
(defined $union->{PROPERTIES}) &&
|
||||||
|
($res .= DumpProperties($union->{PROPERTIES}));
|
||||||
|
$res .= "union {\n";
|
||||||
|
foreach my $e (@{$union->{ELEMENTS}}) {
|
||||||
|
$res .= DumpUnionElement($e);
|
||||||
|
}
|
||||||
|
$res .= "}";
|
||||||
|
|
||||||
|
return $res;
|
||||||
|
}
|
||||||
|
|
||||||
|
#####################################################################
|
||||||
|
# dump a type
|
||||||
|
sub DumpType($)
|
||||||
|
{
|
||||||
|
my($data) = shift;
|
||||||
|
|
||||||
|
if (ref($data) eq "HASH") {
|
||||||
|
return DumpStruct($data) if ($data->{TYPE} eq "STRUCT");
|
||||||
|
return DumpUnion($data) if ($data->{TYPE} eq "UNION");
|
||||||
|
return DumpEnum($data) if ($data->{TYPE} eq "ENUM");
|
||||||
|
return DumpBitmap($data) if ($data->{TYPE} eq "BITMAP");
|
||||||
|
} else {
|
||||||
|
return $data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#####################################################################
|
||||||
|
# dump a typedef
|
||||||
|
sub DumpTypedef($)
|
||||||
|
{
|
||||||
|
my($typedef) = shift;
|
||||||
|
my($res);
|
||||||
|
|
||||||
|
$res .= "typedef ";
|
||||||
|
$res .= DumpType($typedef->{DATA});
|
||||||
|
$res .= " $typedef->{NAME};\n\n";
|
||||||
|
|
||||||
|
return $res;
|
||||||
|
}
|
||||||
|
|
||||||
|
#####################################################################
|
||||||
|
# dump a typedef
|
||||||
|
sub DumpFunction($)
|
||||||
|
{
|
||||||
|
my($function) = shift;
|
||||||
|
my($first) = 1;
|
||||||
|
my($res);
|
||||||
|
|
||||||
|
$res .= DumpType($function->{RETURN_TYPE});
|
||||||
|
$res .= " $function->{NAME}(\n";
|
||||||
|
for my $d (@{$function->{ELEMENTS}}) {
|
||||||
|
unless ($first) { $res .= ",\n"; } $first = 0;
|
||||||
|
$res .= DumpElement($d);
|
||||||
|
}
|
||||||
|
$res .= "\n);\n\n";
|
||||||
|
|
||||||
|
return $res;
|
||||||
|
}
|
||||||
|
|
||||||
|
#####################################################################
|
||||||
|
# dump a module header
|
||||||
|
sub DumpInterfaceProperties($)
|
||||||
|
{
|
||||||
|
my($header) = shift;
|
||||||
|
my($data) = $header->{DATA};
|
||||||
|
my($first) = 1;
|
||||||
|
my($res);
|
||||||
|
|
||||||
|
$res .= "[\n";
|
||||||
|
foreach my $k (keys %{$data}) {
|
||||||
|
$first || ($res .= ",\n"); $first = 0;
|
||||||
|
$res .= "$k($data->{$k})";
|
||||||
|
}
|
||||||
|
$res .= "\n]\n";
|
||||||
|
|
||||||
|
return $res;
|
||||||
|
}
|
||||||
|
|
||||||
|
#####################################################################
|
||||||
|
# dump the interface definitions
|
||||||
|
sub DumpInterface($)
|
||||||
|
{
|
||||||
|
my($interface) = shift;
|
||||||
|
my($data) = $interface->{DATA};
|
||||||
|
my($res);
|
||||||
|
|
||||||
|
$res .= DumpInterfaceProperties($interface->{PROPERTIES});
|
||||||
|
|
||||||
|
$res .= "interface $interface->{NAME}\n{\n";
|
||||||
|
foreach my $d (@{$data}) {
|
||||||
|
($d->{TYPE} eq "TYPEDEF") &&
|
||||||
|
($res .= DumpTypedef($d));
|
||||||
|
($d->{TYPE} eq "FUNCTION") &&
|
||||||
|
($res .= DumpFunction($d));
|
||||||
|
}
|
||||||
|
$res .= "}\n";
|
||||||
|
|
||||||
|
return $res;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#####################################################################
|
||||||
|
# dump a parsed IDL structure back into an IDL file
|
||||||
|
sub Dump($)
|
||||||
|
{
|
||||||
|
my($idl) = shift;
|
||||||
|
my($res);
|
||||||
|
|
||||||
|
$res = "/* Dumped by pidl */\n\n";
|
||||||
|
foreach my $x (@{$idl}) {
|
||||||
|
($x->{TYPE} eq "INTERFACE") &&
|
||||||
|
($res .= DumpInterface($x));
|
||||||
|
}
|
||||||
|
return $res;
|
||||||
|
}
|
||||||
|
|
||||||
|
1;
|
1444
tools/pidl/lib/Parse/Pidl/Expr.pm
Normal file
1444
tools/pidl/lib/Parse/Pidl/Expr.pm
Normal file
File diff suppressed because it is too large
Load Diff
2687
tools/pidl/lib/Parse/Pidl/IDL.pm
Normal file
2687
tools/pidl/lib/Parse/Pidl/IDL.pm
Normal file
File diff suppressed because it is too large
Load Diff
1441
tools/pidl/lib/Parse/Pidl/NDR.pm
Normal file
1441
tools/pidl/lib/Parse/Pidl/NDR.pm
Normal file
File diff suppressed because it is too large
Load Diff
131
tools/pidl/lib/Parse/Pidl/ODL.pm
Normal file
131
tools/pidl/lib/Parse/Pidl/ODL.pm
Normal file
|
@ -0,0 +1,131 @@
|
||||||
|
##########################################
|
||||||
|
# Converts ODL stuctures to IDL structures
|
||||||
|
# (C) 2004-2005, 2008 Jelmer Vernooij <jelmer@samba.org>
|
||||||
|
|
||||||
|
package Parse::Pidl::ODL;
|
||||||
|
|
||||||
|
use Parse::Pidl qw(error);
|
||||||
|
use Parse::Pidl::IDL;
|
||||||
|
use Parse::Pidl::Util qw(has_property unmake_str);
|
||||||
|
use Parse::Pidl::Typelist qw(hasType getType);
|
||||||
|
use File::Basename;
|
||||||
|
use strict;
|
||||||
|
|
||||||
|
use vars qw($VERSION);
|
||||||
|
$VERSION = '0.01';
|
||||||
|
|
||||||
|
sub FunctionAddObjArgs($)
|
||||||
|
{
|
||||||
|
my $e = shift;
|
||||||
|
|
||||||
|
unshift(@{$e->{ELEMENTS}}, {
|
||||||
|
'NAME' => 'ORPCthis',
|
||||||
|
'POINTERS' => 0,
|
||||||
|
'PROPERTIES' => { 'in' => '1' },
|
||||||
|
'TYPE' => 'ORPCTHIS',
|
||||||
|
'FILE' => $e->{FILE},
|
||||||
|
'LINE' => $e->{LINE}
|
||||||
|
});
|
||||||
|
unshift(@{$e->{ELEMENTS}}, {
|
||||||
|
'NAME' => 'ORPCthat',
|
||||||
|
'POINTERS' => 1,
|
||||||
|
'PROPERTIES' => { 'out' => '1', 'ref' => '1' },
|
||||||
|
'TYPE' => 'ORPCTHAT',
|
||||||
|
'FILE' => $e->{FILE},
|
||||||
|
'LINE' => $e->{LINE}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
sub ReplaceInterfacePointers($)
|
||||||
|
{
|
||||||
|
my ($e) = @_;
|
||||||
|
foreach my $x (@{$e->{ELEMENTS}}) {
|
||||||
|
next unless (hasType($x->{TYPE}));
|
||||||
|
next unless ref(getType($x->{TYPE})->{DATA}) eq "HASH";
|
||||||
|
next unless getType($x->{TYPE})->{DATA}->{TYPE} eq "INTERFACE";
|
||||||
|
|
||||||
|
$x->{TYPE} = "MInterfacePointer";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Add ORPC specific bits to an interface.
|
||||||
|
sub ODL2IDL
|
||||||
|
{
|
||||||
|
my ($odl, $basedir, $opt_incdirs) = (@_);
|
||||||
|
my $addedorpc = 0;
|
||||||
|
my $interfaces = {};
|
||||||
|
|
||||||
|
foreach my $x (@$odl) {
|
||||||
|
if ($x->{TYPE} eq "IMPORT") {
|
||||||
|
foreach my $idl_file (@{$x->{PATHS}}) {
|
||||||
|
$idl_file = unmake_str($idl_file);
|
||||||
|
my $idl_path = undef;
|
||||||
|
foreach ($basedir, @$opt_incdirs) {
|
||||||
|
if (-f "$_/$idl_file") {
|
||||||
|
$idl_path = "$_/$idl_file";
|
||||||
|
last;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
unless ($idl_path) {
|
||||||
|
error($x, "Unable to open include file `$idl_file'");
|
||||||
|
next;
|
||||||
|
}
|
||||||
|
my $podl = Parse::Pidl::IDL::parse_file($idl_path, $opt_incdirs);
|
||||||
|
if (defined(@$podl)) {
|
||||||
|
require Parse::Pidl::Typelist;
|
||||||
|
my $basename = basename($idl_path, ".idl");
|
||||||
|
|
||||||
|
Parse::Pidl::Typelist::LoadIdl($podl, $basename);
|
||||||
|
my $pidl = ODL2IDL($podl, $basedir, $opt_incdirs);
|
||||||
|
|
||||||
|
foreach my $y (@$pidl) {
|
||||||
|
if ($y->{TYPE} eq "INTERFACE") {
|
||||||
|
$interfaces->{$y->{NAME}} = $y;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
error($x, "Failed to parse $idl_path");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($x->{TYPE} eq "INTERFACE") {
|
||||||
|
$interfaces->{$x->{NAME}} = $x;
|
||||||
|
# Add [in] ORPCTHIS *this, [out] ORPCTHAT *that
|
||||||
|
# and replace interfacepointers with MInterfacePointer
|
||||||
|
# for 'object' interfaces
|
||||||
|
if (has_property($x, "object")) {
|
||||||
|
foreach my $e (@{$x->{DATA}}) {
|
||||||
|
($e->{TYPE} eq "FUNCTION") && FunctionAddObjArgs($e);
|
||||||
|
ReplaceInterfacePointers($e);
|
||||||
|
}
|
||||||
|
$addedorpc = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($x->{BASE}) {
|
||||||
|
my $base = $interfaces->{$x->{BASE}};
|
||||||
|
|
||||||
|
unless (defined($base)) {
|
||||||
|
error($x, "Undefined base interface `$x->{BASE}'");
|
||||||
|
} else {
|
||||||
|
foreach my $fn (reverse @{$base->{DATA}}) {
|
||||||
|
next unless ($fn->{TYPE} eq "FUNCTION");
|
||||||
|
push (@{$x->{INHERITED_FUNCTIONS}}, $fn);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unshift (@$odl, {
|
||||||
|
TYPE => "IMPORT",
|
||||||
|
PATHS => [ "\"orpc.idl\"" ],
|
||||||
|
FILE => undef,
|
||||||
|
LINE => undef
|
||||||
|
}) if ($addedorpc);
|
||||||
|
|
||||||
|
|
||||||
|
return $odl;
|
||||||
|
}
|
||||||
|
|
||||||
|
1;
|
418
tools/pidl/lib/Parse/Pidl/Samba3/ClientNDR.pm
Normal file
418
tools/pidl/lib/Parse/Pidl/Samba3/ClientNDR.pm
Normal file
|
@ -0,0 +1,418 @@
|
||||||
|
###################################################
|
||||||
|
# Samba3 client generator for IDL structures
|
||||||
|
# on top of Samba4 style NDR functions
|
||||||
|
# Copyright jelmer@samba.org 2005-2006
|
||||||
|
# Copyright gd@samba.org 2008
|
||||||
|
# released under the GNU GPL
|
||||||
|
|
||||||
|
package Parse::Pidl::Samba3::ClientNDR;
|
||||||
|
|
||||||
|
use Exporter;
|
||||||
|
@ISA = qw(Exporter);
|
||||||
|
@EXPORT_OK = qw(ParseFunction $res $res_hdr);
|
||||||
|
|
||||||
|
use strict;
|
||||||
|
use Parse::Pidl qw(fatal warning error);
|
||||||
|
use Parse::Pidl::Util qw(has_property ParseExpr);
|
||||||
|
use Parse::Pidl::NDR qw(ContainsPipe);
|
||||||
|
use Parse::Pidl::Typelist qw(mapTypeName);
|
||||||
|
use Parse::Pidl::Samba4 qw(DeclLong);
|
||||||
|
use Parse::Pidl::Samba4::Header qw(GenerateFunctionInEnv GenerateFunctionOutEnv);
|
||||||
|
|
||||||
|
use vars qw($VERSION);
|
||||||
|
$VERSION = '0.01';
|
||||||
|
|
||||||
|
sub indent($) { my ($self) = @_; $self->{tabs}.="\t"; }
|
||||||
|
sub deindent($) { my ($self) = @_; $self->{tabs} = substr($self->{tabs}, 1); }
|
||||||
|
sub pidl($$) { my ($self,$txt) = @_; $self->{res} .= $txt ? "$self->{tabs}$txt\n" : "\n"; }
|
||||||
|
sub pidl_hdr($$) { my ($self, $txt) = @_; $self->{res_hdr} .= "$txt\n"; }
|
||||||
|
sub fn_declare($$) { my ($self,$n) = @_; $self->pidl($n); $self->pidl_hdr("$n;"); }
|
||||||
|
|
||||||
|
sub genpad($)
|
||||||
|
{
|
||||||
|
my ($s) = @_;
|
||||||
|
my $nt = int((length($s)+1)/8);
|
||||||
|
my $lt = ($nt*8)-1;
|
||||||
|
my $ns = (length($s)-$lt);
|
||||||
|
return "\t"x($nt)." "x($ns);
|
||||||
|
}
|
||||||
|
|
||||||
|
sub new($)
|
||||||
|
{
|
||||||
|
my ($class) = shift;
|
||||||
|
my $self = { res => "", res_hdr => "", tabs => "" };
|
||||||
|
bless($self, $class);
|
||||||
|
}
|
||||||
|
|
||||||
|
sub ElementDirection($)
|
||||||
|
{
|
||||||
|
my ($e) = @_;
|
||||||
|
|
||||||
|
return "[in,out]" if (has_property($e, "in") and has_property($e, "out"));
|
||||||
|
return "[in]" if (has_property($e, "in"));
|
||||||
|
return "[out]" if (has_property($e, "out"));
|
||||||
|
return "[in,out]";
|
||||||
|
}
|
||||||
|
|
||||||
|
sub HeaderProperties($$)
|
||||||
|
{
|
||||||
|
my($props,$ignores) = @_;
|
||||||
|
my $ret = "";
|
||||||
|
|
||||||
|
foreach my $d (keys %{$props}) {
|
||||||
|
next if (grep(/^$d$/, @$ignores));
|
||||||
|
if($props->{$d} ne "1") {
|
||||||
|
$ret.= "$d($props->{$d}),";
|
||||||
|
} else {
|
||||||
|
$ret.="$d,";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($ret) {
|
||||||
|
return "[" . substr($ret, 0, -1) . "]";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sub ParseInvalidResponse($$)
|
||||||
|
{
|
||||||
|
my ($self, $type) = @_;
|
||||||
|
|
||||||
|
if ($type eq "sync") {
|
||||||
|
$self->pidl("return NT_STATUS_INVALID_NETWORK_RESPONSE;");
|
||||||
|
} elsif ($type eq "async") {
|
||||||
|
$self->pidl("tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);");
|
||||||
|
$self->pidl("return;");
|
||||||
|
} else {
|
||||||
|
die("ParseInvalidResponse($type)");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sub ParseFunctionAsyncState($$$)
|
||||||
|
{
|
||||||
|
my ($self, $if, $fn) = @_;
|
||||||
|
|
||||||
|
my $state_str = "struct rpccli_$fn->{NAME}_state";
|
||||||
|
my $done_fn = "rpccli_$fn->{NAME}_done";
|
||||||
|
|
||||||
|
$self->pidl("$state_str {");
|
||||||
|
$self->indent;
|
||||||
|
$self->pidl("TALLOC_CTX *out_mem_ctx;");
|
||||||
|
if (defined($fn->{RETURN_TYPE})) {
|
||||||
|
$self->pidl(mapTypeName($fn->{RETURN_TYPE}). " result;");
|
||||||
|
}
|
||||||
|
$self->deindent;
|
||||||
|
$self->pidl("};");
|
||||||
|
$self->pidl("");
|
||||||
|
$self->pidl("static void $done_fn(struct tevent_req *subreq);");
|
||||||
|
$self->pidl("");
|
||||||
|
}
|
||||||
|
|
||||||
|
sub ParseFunctionAsyncSend($$$)
|
||||||
|
{
|
||||||
|
my ($self, $if, $fn) = @_;
|
||||||
|
|
||||||
|
my $fn_args = "";
|
||||||
|
my $uif = uc($if);
|
||||||
|
my $ufn = "NDR_".uc($fn->{NAME});
|
||||||
|
my $state_str = "struct rpccli_$fn->{NAME}_state";
|
||||||
|
my $done_fn = "rpccli_$fn->{NAME}_done";
|
||||||
|
my $out_mem_ctx = "rpccli_$fn->{NAME}_out_memory";
|
||||||
|
my $fn_str = "struct tevent_req *rpccli_$fn->{NAME}_send";
|
||||||
|
my $pad = genpad($fn_str);
|
||||||
|
|
||||||
|
$fn_args .= "TALLOC_CTX *mem_ctx";
|
||||||
|
$fn_args .= ",\n" . $pad . "struct tevent_context *ev";
|
||||||
|
$fn_args .= ",\n" . $pad . "struct rpc_pipe_client *cli";
|
||||||
|
|
||||||
|
foreach (@{$fn->{ELEMENTS}}) {
|
||||||
|
my $dir = ElementDirection($_);
|
||||||
|
my $prop = HeaderProperties($_->{PROPERTIES}, ["in", "out"]);
|
||||||
|
$fn_args .= ",\n" . $pad . DeclLong($_, "_") . " /* $dir $prop */";
|
||||||
|
}
|
||||||
|
|
||||||
|
$self->fn_declare("$fn_str($fn_args)");
|
||||||
|
$self->pidl("{");
|
||||||
|
$self->indent;
|
||||||
|
$self->pidl("struct tevent_req *req;");
|
||||||
|
$self->pidl("$state_str *state;");
|
||||||
|
$self->pidl("struct tevent_req *subreq;");
|
||||||
|
$self->pidl("");
|
||||||
|
$self->pidl("req = tevent_req_create(mem_ctx, &state,");
|
||||||
|
$self->pidl("\t\t\t$state_str);");
|
||||||
|
$self->pidl("if (req == NULL) {");
|
||||||
|
$self->indent;
|
||||||
|
$self->pidl("return NULL;");
|
||||||
|
$self->deindent;
|
||||||
|
$self->pidl("}");
|
||||||
|
$self->pidl("state->out_mem_ctx = NULL;");
|
||||||
|
$self->pidl("");
|
||||||
|
|
||||||
|
my $out_params = 0;
|
||||||
|
foreach (@{$fn->{ELEMENTS}}) {
|
||||||
|
if (grep(/out/, @{$_->{DIRECTION}})) {
|
||||||
|
$out_params++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($out_params > 0) {
|
||||||
|
$self->pidl("state->out_mem_ctx = talloc_named_const(state, 0,");
|
||||||
|
$self->pidl("\t\t \"$out_mem_ctx\");");
|
||||||
|
$self->pidl("if (tevent_req_nomem(state->out_mem_ctx, req)) {");
|
||||||
|
$self->indent;
|
||||||
|
$self->pidl("return tevent_req_post(req, ev);");
|
||||||
|
$self->deindent;
|
||||||
|
$self->pidl("}");
|
||||||
|
$self->pidl("");
|
||||||
|
}
|
||||||
|
|
||||||
|
$fn_str = "subreq = dcerpc_$fn->{NAME}_send";
|
||||||
|
$pad = "\t" . genpad($fn_str);
|
||||||
|
$fn_args = "state,\n" . $pad . "ev,\n" . $pad . "cli->binding_handle";
|
||||||
|
foreach (@{$fn->{ELEMENTS}}) {
|
||||||
|
$fn_args .= ",\n" . $pad . "_". $_->{NAME};
|
||||||
|
}
|
||||||
|
|
||||||
|
$self->pidl("$fn_str($fn_args);");
|
||||||
|
$self->pidl("if (tevent_req_nomem(subreq, req)) {");
|
||||||
|
$self->indent;
|
||||||
|
$self->pidl("return tevent_req_post(req, ev);");
|
||||||
|
$self->deindent;
|
||||||
|
$self->pidl("}");
|
||||||
|
$self->pidl("tevent_req_set_callback(subreq, $done_fn, req);");
|
||||||
|
$self->pidl("return req;");
|
||||||
|
$self->deindent;
|
||||||
|
$self->pidl("}");
|
||||||
|
$self->pidl("");
|
||||||
|
}
|
||||||
|
|
||||||
|
sub ParseFunctionAsyncDone($$$)
|
||||||
|
{
|
||||||
|
my ($self, $if, $fn) = @_;
|
||||||
|
|
||||||
|
my $state_str = "struct rpccli_$fn->{NAME}_state";
|
||||||
|
my $done_fn = "rpccli_$fn->{NAME}_done";
|
||||||
|
|
||||||
|
$self->pidl("static void $done_fn(struct tevent_req *subreq)");
|
||||||
|
$self->pidl("{");
|
||||||
|
$self->indent;
|
||||||
|
$self->pidl("struct tevent_req *req = tevent_req_callback_data(");
|
||||||
|
$self->pidl("\tsubreq, struct tevent_req);");
|
||||||
|
$self->pidl("$state_str *state = tevent_req_data(");
|
||||||
|
$self->pidl("\treq, $state_str);");
|
||||||
|
$self->pidl("NTSTATUS status;");
|
||||||
|
$self->pidl("TALLOC_CTX *mem_ctx;");
|
||||||
|
$self->pidl("");
|
||||||
|
|
||||||
|
$self->pidl("if (state->out_mem_ctx) {");
|
||||||
|
$self->indent;
|
||||||
|
$self->pidl("mem_ctx = state->out_mem_ctx;");
|
||||||
|
$self->deindent;
|
||||||
|
$self->pidl("} else {");
|
||||||
|
$self->indent;
|
||||||
|
$self->pidl("mem_ctx = state;");
|
||||||
|
$self->deindent;
|
||||||
|
$self->pidl("}");
|
||||||
|
$self->pidl("");
|
||||||
|
|
||||||
|
my $fn_str = "status = dcerpc_$fn->{NAME}_recv";
|
||||||
|
my $pad = "\t" . genpad($fn_str);
|
||||||
|
my $fn_args = "subreq,\n" . $pad . "mem_ctx";
|
||||||
|
if (defined($fn->{RETURN_TYPE})) {
|
||||||
|
$fn_args .= ",\n" . $pad . "&state->result";
|
||||||
|
}
|
||||||
|
|
||||||
|
$self->pidl("$fn_str($fn_args);");
|
||||||
|
$self->pidl("TALLOC_FREE(subreq);");
|
||||||
|
$self->pidl("if (!NT_STATUS_IS_OK(status)) {");
|
||||||
|
$self->indent;
|
||||||
|
$self->pidl("tevent_req_nterror(req, status);");
|
||||||
|
$self->pidl("return;");
|
||||||
|
$self->deindent;
|
||||||
|
$self->pidl("}");
|
||||||
|
$self->pidl("");
|
||||||
|
|
||||||
|
$self->pidl("tevent_req_done(req);");
|
||||||
|
$self->deindent;
|
||||||
|
$self->pidl("}");
|
||||||
|
$self->pidl("");
|
||||||
|
}
|
||||||
|
|
||||||
|
sub ParseFunctionAsyncRecv($$$)
|
||||||
|
{
|
||||||
|
my ($self, $if, $fn) = @_;
|
||||||
|
|
||||||
|
my $fn_args = "";
|
||||||
|
my $state_str = "struct rpccli_$fn->{NAME}_state";
|
||||||
|
my $fn_str = "NTSTATUS rpccli_$fn->{NAME}_recv";
|
||||||
|
my $pad = genpad($fn_str);
|
||||||
|
|
||||||
|
$fn_args .= "struct tevent_req *req,\n" . $pad . "TALLOC_CTX *mem_ctx";
|
||||||
|
|
||||||
|
if (defined($fn->{RETURN_TYPE})) {
|
||||||
|
$fn_args .= ",\n" . $pad . "$fn->{RETURN_TYPE} *result";
|
||||||
|
}
|
||||||
|
|
||||||
|
$self->fn_declare("$fn_str($fn_args)");
|
||||||
|
$self->pidl("{");
|
||||||
|
$self->indent;
|
||||||
|
$self->pidl("$state_str *state = tevent_req_data(");
|
||||||
|
$self->pidl("\treq, $state_str);");
|
||||||
|
$self->pidl("NTSTATUS status;");
|
||||||
|
$self->pidl("");
|
||||||
|
$self->pidl("if (tevent_req_is_nterror(req, &status)) {");
|
||||||
|
$self->indent;
|
||||||
|
$self->pidl("tevent_req_received(req);");
|
||||||
|
$self->pidl("return status;");
|
||||||
|
$self->deindent;
|
||||||
|
$self->pidl("}");
|
||||||
|
$self->pidl("");
|
||||||
|
|
||||||
|
$self->pidl("/* Steal possible out parameters to the callers context */");
|
||||||
|
$self->pidl("talloc_steal(mem_ctx, state->out_mem_ctx);");
|
||||||
|
$self->pidl("");
|
||||||
|
|
||||||
|
if (defined($fn->{RETURN_TYPE})) {
|
||||||
|
$self->pidl("/* Return result */");
|
||||||
|
$self->pidl("*result = state->result;");
|
||||||
|
$self->pidl("");
|
||||||
|
}
|
||||||
|
|
||||||
|
$self->pidl("tevent_req_received(req);");
|
||||||
|
$self->pidl("return NT_STATUS_OK;");
|
||||||
|
$self->deindent;
|
||||||
|
$self->pidl("}");
|
||||||
|
$self->pidl("");
|
||||||
|
}
|
||||||
|
|
||||||
|
sub ParseFunctionSync($$$)
|
||||||
|
{
|
||||||
|
my ($self, $if, $fn) = @_;
|
||||||
|
|
||||||
|
my $fn_args = "";
|
||||||
|
my $uif = uc($if);
|
||||||
|
my $ufn = "NDR_".uc($fn->{NAME});
|
||||||
|
my $fn_str = "NTSTATUS rpccli_$fn->{NAME}";
|
||||||
|
my $pad = genpad($fn_str);
|
||||||
|
|
||||||
|
$fn_args .= "struct rpc_pipe_client *cli,\n" . $pad . "TALLOC_CTX *mem_ctx";
|
||||||
|
|
||||||
|
foreach (@{$fn->{ELEMENTS}}) {
|
||||||
|
my $dir = ElementDirection($_);
|
||||||
|
my $prop = HeaderProperties($_->{PROPERTIES}, ["in", "out"]);
|
||||||
|
$fn_args .= ",\n" . $pad . DeclLong($_, "_") . " /* $dir $prop */";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (defined($fn->{RETURN_TYPE}) && ($fn->{RETURN_TYPE} eq "WERROR")) {
|
||||||
|
$fn_args .= ",\n" . $pad . "WERROR *werror";
|
||||||
|
}
|
||||||
|
|
||||||
|
$self->fn_declare("$fn_str($fn_args)");
|
||||||
|
$self->pidl("{");
|
||||||
|
$self->indent;
|
||||||
|
if (defined($fn->{RETURN_TYPE})) {
|
||||||
|
$self->pidl(mapTypeName($fn->{RETURN_TYPE})." result;");
|
||||||
|
}
|
||||||
|
$self->pidl("NTSTATUS status;");
|
||||||
|
$self->pidl("");
|
||||||
|
|
||||||
|
$fn_str = "status = dcerpc_$fn->{NAME}";
|
||||||
|
$pad = "\t" . genpad($fn_str);
|
||||||
|
$fn_args = "cli->binding_handle,\n" . $pad . "mem_ctx";
|
||||||
|
foreach (@{$fn->{ELEMENTS}}) {
|
||||||
|
$fn_args .= ",\n" . $pad . "_". $_->{NAME};
|
||||||
|
}
|
||||||
|
if (defined($fn->{RETURN_TYPE})) {
|
||||||
|
$fn_args .= ",\n" . $pad . "&result";
|
||||||
|
}
|
||||||
|
|
||||||
|
$self->pidl("$fn_str($fn_args);");
|
||||||
|
$self->pidl("if (!NT_STATUS_IS_OK(status)) {");
|
||||||
|
$self->indent;
|
||||||
|
$self->pidl("return status;");
|
||||||
|
$self->deindent;
|
||||||
|
$self->pidl("}");
|
||||||
|
$self->pidl("");
|
||||||
|
|
||||||
|
$self->pidl("/* Return result */");
|
||||||
|
if (not $fn->{RETURN_TYPE}) {
|
||||||
|
$self->pidl("return NT_STATUS_OK;");
|
||||||
|
} elsif ($fn->{RETURN_TYPE} eq "NTSTATUS") {
|
||||||
|
$self->pidl("return result;");
|
||||||
|
} elsif ($fn->{RETURN_TYPE} eq "WERROR") {
|
||||||
|
$self->pidl("if (werror) {");
|
||||||
|
$self->indent;
|
||||||
|
$self->pidl("*werror = result;");
|
||||||
|
$self->deindent;
|
||||||
|
$self->pidl("}");
|
||||||
|
$self->pidl("");
|
||||||
|
$self->pidl("return werror_to_ntstatus(result);");
|
||||||
|
} else {
|
||||||
|
warning($fn->{ORIGINAL}, "Unable to convert $fn->{RETURN_TYPE} to NTSTATUS");
|
||||||
|
$self->pidl("return NT_STATUS_OK;");
|
||||||
|
}
|
||||||
|
|
||||||
|
$self->deindent;
|
||||||
|
$self->pidl("}");
|
||||||
|
$self->pidl("");
|
||||||
|
}
|
||||||
|
|
||||||
|
sub ParseFunction($$$)
|
||||||
|
{
|
||||||
|
my ($self, $if, $fn) = @_;
|
||||||
|
|
||||||
|
$self->ParseFunctionAsyncState($if, $fn);
|
||||||
|
$self->ParseFunctionAsyncSend($if, $fn);
|
||||||
|
$self->ParseFunctionAsyncDone($if, $fn);
|
||||||
|
$self->ParseFunctionAsyncRecv($if, $fn);
|
||||||
|
|
||||||
|
$self->ParseFunctionSync($if, $fn);
|
||||||
|
}
|
||||||
|
|
||||||
|
sub ParseInterface($$)
|
||||||
|
{
|
||||||
|
my ($self, $if) = @_;
|
||||||
|
|
||||||
|
my $uif = uc($if->{NAME});
|
||||||
|
|
||||||
|
$self->pidl_hdr("#ifndef __CLI_$uif\__");
|
||||||
|
$self->pidl_hdr("#define __CLI_$uif\__");
|
||||||
|
foreach my $fn (@{$if->{FUNCTIONS}}) {
|
||||||
|
next if has_property($fn, "noopnum");
|
||||||
|
next if has_property($fn, "todo");
|
||||||
|
|
||||||
|
my $skip = 0;
|
||||||
|
foreach my $e (@{$fn->{ELEMENTS}}) {
|
||||||
|
if (ContainsPipe($e, $e->{LEVELS}[0])) {
|
||||||
|
$skip = 1;
|
||||||
|
last;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
next if $skip;
|
||||||
|
|
||||||
|
$self->ParseFunction($if->{NAME}, $fn);
|
||||||
|
}
|
||||||
|
$self->pidl_hdr("#endif /* __CLI_$uif\__ */");
|
||||||
|
}
|
||||||
|
|
||||||
|
sub Parse($$$$)
|
||||||
|
{
|
||||||
|
my($self,$ndr,$header,$c_header) = @_;
|
||||||
|
|
||||||
|
$self->pidl("/*");
|
||||||
|
$self->pidl(" * Unix SMB/CIFS implementation.");
|
||||||
|
$self->pidl(" * client auto-generated by pidl. DO NOT MODIFY!");
|
||||||
|
$self->pidl(" */");
|
||||||
|
$self->pidl("");
|
||||||
|
$self->pidl("#include \"includes.h\"");
|
||||||
|
$self->pidl("#include \"$header\"");
|
||||||
|
$self->pidl_hdr("#include \"$c_header\"");
|
||||||
|
$self->pidl("");
|
||||||
|
|
||||||
|
foreach (@$ndr) {
|
||||||
|
$self->ParseInterface($_) if ($_->{TYPE} eq "INTERFACE");
|
||||||
|
}
|
||||||
|
|
||||||
|
return ($self->{res}, $self->{res_hdr});
|
||||||
|
}
|
||||||
|
|
||||||
|
1;
|
309
tools/pidl/lib/Parse/Pidl/Samba3/ServerNDR.pm
Normal file
309
tools/pidl/lib/Parse/Pidl/Samba3/ServerNDR.pm
Normal file
|
@ -0,0 +1,309 @@
|
||||||
|
###################################################
|
||||||
|
# Samba3 server generator for IDL structures
|
||||||
|
# on top of Samba4 style NDR functions
|
||||||
|
# Copyright jelmer@samba.org 2005-2006
|
||||||
|
# released under the GNU GPL
|
||||||
|
|
||||||
|
package Parse::Pidl::Samba3::ServerNDR;
|
||||||
|
|
||||||
|
use Exporter;
|
||||||
|
@ISA = qw(Exporter);
|
||||||
|
@EXPORT_OK = qw(DeclLevel);
|
||||||
|
|
||||||
|
use strict;
|
||||||
|
use Parse::Pidl qw(warning error fatal);
|
||||||
|
use Parse::Pidl::Typelist qw(mapTypeName scalar_is_reference);
|
||||||
|
use Parse::Pidl::Util qw(ParseExpr has_property is_constant);
|
||||||
|
use Parse::Pidl::NDR qw(GetNextLevel);
|
||||||
|
use Parse::Pidl::Samba4 qw(ElementStars DeclLong);
|
||||||
|
use Parse::Pidl::Samba4::Header qw(GenerateFunctionOutEnv);
|
||||||
|
|
||||||
|
use vars qw($VERSION);
|
||||||
|
$VERSION = '0.01';
|
||||||
|
|
||||||
|
my $res;
|
||||||
|
my $res_hdr;
|
||||||
|
my $tabs = "";
|
||||||
|
sub indent() { $tabs.="\t"; }
|
||||||
|
sub deindent() { $tabs = substr($tabs, 1); }
|
||||||
|
sub pidl($) { my ($txt) = @_; $res .= $txt?$tabs.(shift)."\n":"\n"; }
|
||||||
|
sub pidl_hdr($) { $res_hdr .= (shift)."\n"; }
|
||||||
|
sub fn_declare($) { my ($n) = @_; pidl $n; pidl_hdr "$n;"; }
|
||||||
|
|
||||||
|
sub DeclLevel($$)
|
||||||
|
{
|
||||||
|
my ($e, $l) = @_;
|
||||||
|
my $res = "";
|
||||||
|
|
||||||
|
if (has_property($e, "charset")) {
|
||||||
|
$res .= "const char";
|
||||||
|
} else {
|
||||||
|
$res .= mapTypeName($e->{TYPE});
|
||||||
|
}
|
||||||
|
|
||||||
|
my $stars = ElementStars($e, $l);
|
||||||
|
|
||||||
|
$res .= " ".$stars unless ($stars eq "");
|
||||||
|
|
||||||
|
return $res;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub AllocOutVar($$$$$)
|
||||||
|
{
|
||||||
|
my ($e, $mem_ctx, $name, $env, $fail) = @_;
|
||||||
|
|
||||||
|
my $l = $e->{LEVELS}[0];
|
||||||
|
|
||||||
|
# we skip pointer to arrays
|
||||||
|
if ($l->{TYPE} eq "POINTER") {
|
||||||
|
my $nl = GetNextLevel($e, $l);
|
||||||
|
$l = $nl if ($nl->{TYPE} eq "ARRAY");
|
||||||
|
} elsif
|
||||||
|
|
||||||
|
# we don't support multi-dimentional arrays yet
|
||||||
|
($l->{TYPE} eq "ARRAY") {
|
||||||
|
my $nl = GetNextLevel($e, $l);
|
||||||
|
if ($nl->{TYPE} eq "ARRAY") {
|
||||||
|
fatal($e->{ORIGINAL},"multi-dimentional [out] arrays are not supported!");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
# neither pointer nor array, no need to alloc something.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($l->{TYPE} eq "ARRAY") {
|
||||||
|
unless(defined($l->{SIZE_IS})) {
|
||||||
|
error($e->{ORIGINAL}, "No size known for array `$e->{NAME}'");
|
||||||
|
pidl "#error No size known for array `$e->{NAME}'";
|
||||||
|
} else {
|
||||||
|
my $size = ParseExpr($l->{SIZE_IS}, $env, $e);
|
||||||
|
pidl "$name = talloc_zero_array($mem_ctx, " . DeclLevel($e, 1) . ", $size);";
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
pidl "$name = talloc_zero($mem_ctx, " . DeclLevel($e, 1) . ");";
|
||||||
|
}
|
||||||
|
|
||||||
|
pidl "if ($name == NULL) {";
|
||||||
|
$fail->();
|
||||||
|
pidl "}";
|
||||||
|
pidl "";
|
||||||
|
}
|
||||||
|
|
||||||
|
sub CallWithStruct($$$$)
|
||||||
|
{
|
||||||
|
my ($pipes_struct, $mem_ctx, $fn, $fail) = @_;
|
||||||
|
my $env = GenerateFunctionOutEnv($fn);
|
||||||
|
my $hasout = 0;
|
||||||
|
foreach (@{$fn->{ELEMENTS}}) {
|
||||||
|
if (grep(/out/, @{$_->{DIRECTION}})) { $hasout = 1; }
|
||||||
|
}
|
||||||
|
|
||||||
|
pidl "ZERO_STRUCT(r->out);" if ($hasout);
|
||||||
|
|
||||||
|
my $proto = "_$fn->{NAME}(struct pipes_struct *p, struct $fn->{NAME} *r";
|
||||||
|
my $ret = "_$fn->{NAME}($pipes_struct, r";
|
||||||
|
foreach (@{$fn->{ELEMENTS}}) {
|
||||||
|
my @dir = @{$_->{DIRECTION}};
|
||||||
|
if (grep(/in/, @dir) and grep(/out/, @dir)) {
|
||||||
|
pidl "r->out.$_->{NAME} = r->in.$_->{NAME};";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (@{$fn->{ELEMENTS}}) {
|
||||||
|
my @dir = @{$_->{DIRECTION}};
|
||||||
|
if (grep(/in/, @dir) and grep(/out/, @dir)) {
|
||||||
|
# noop
|
||||||
|
} elsif (grep(/out/, @dir) and not
|
||||||
|
has_property($_, "represent_as")) {
|
||||||
|
AllocOutVar($_, $mem_ctx, "r->out.$_->{NAME}", $env, $fail);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$ret .= ")";
|
||||||
|
$proto .= ");";
|
||||||
|
|
||||||
|
if ($fn->{RETURN_TYPE}) {
|
||||||
|
$ret = "r->out.result = $ret";
|
||||||
|
$proto = "$fn->{RETURN_TYPE} $proto";
|
||||||
|
} else {
|
||||||
|
$proto = "void $proto";
|
||||||
|
}
|
||||||
|
|
||||||
|
pidl_hdr "$proto";
|
||||||
|
pidl "$ret;";
|
||||||
|
}
|
||||||
|
|
||||||
|
sub ParseFunction($$)
|
||||||
|
{
|
||||||
|
my ($if,$fn) = @_;
|
||||||
|
|
||||||
|
my $op = "NDR_".uc($fn->{NAME});
|
||||||
|
|
||||||
|
pidl "static bool api_$fn->{NAME}(struct pipes_struct *p)";
|
||||||
|
pidl "{";
|
||||||
|
indent;
|
||||||
|
pidl "const struct ndr_interface_call *call;";
|
||||||
|
pidl "struct ndr_pull *pull;";
|
||||||
|
pidl "struct ndr_push *push;";
|
||||||
|
pidl "enum ndr_err_code ndr_err;";
|
||||||
|
pidl "struct $fn->{NAME} *r;";
|
||||||
|
pidl "";
|
||||||
|
pidl "call = &ndr_table_$if->{NAME}.calls[$op];";
|
||||||
|
pidl "";
|
||||||
|
pidl "r = talloc(talloc_tos(), struct $fn->{NAME});";
|
||||||
|
pidl "if (r == NULL) {";
|
||||||
|
pidl "\treturn false;";
|
||||||
|
pidl "}";
|
||||||
|
pidl "";
|
||||||
|
pidl "pull = ndr_pull_init_blob(&p->in_data.data, r);";
|
||||||
|
pidl "if (pull == NULL) {";
|
||||||
|
pidl "\ttalloc_free(r);";
|
||||||
|
pidl "\treturn false;";
|
||||||
|
pidl "}";
|
||||||
|
pidl "";
|
||||||
|
pidl "pull->flags |= LIBNDR_FLAG_REF_ALLOC;";
|
||||||
|
pidl "if (p->endian) {";
|
||||||
|
pidl "\tpull->flags |= LIBNDR_FLAG_BIGENDIAN;";
|
||||||
|
pidl "}";
|
||||||
|
pidl "ndr_err = call->ndr_pull(pull, NDR_IN, r);";
|
||||||
|
pidl "if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {";
|
||||||
|
pidl "\ttalloc_free(r);";
|
||||||
|
pidl "\treturn false;";
|
||||||
|
pidl "}";
|
||||||
|
pidl "";
|
||||||
|
pidl "if (DEBUGLEVEL >= 10) {";
|
||||||
|
pidl "\tNDR_PRINT_FUNCTION_DEBUG($fn->{NAME}, NDR_IN, r);";
|
||||||
|
pidl "}";
|
||||||
|
pidl "";
|
||||||
|
|
||||||
|
CallWithStruct("p", "r", $fn,
|
||||||
|
sub {
|
||||||
|
pidl "\ttalloc_free(r);";
|
||||||
|
pidl "\treturn false;";
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
pidl "";
|
||||||
|
pidl "if (p->fault_state) {";
|
||||||
|
pidl "\ttalloc_free(r);";
|
||||||
|
pidl "\t/* Return true here, srv_pipe_hnd.c will take care */";
|
||||||
|
pidl "\treturn true;";
|
||||||
|
pidl "}";
|
||||||
|
pidl "";
|
||||||
|
pidl "if (DEBUGLEVEL >= 10) {";
|
||||||
|
pidl "\tNDR_PRINT_FUNCTION_DEBUG($fn->{NAME}, NDR_OUT | NDR_SET_VALUES, r);";
|
||||||
|
pidl "}";
|
||||||
|
pidl "";
|
||||||
|
pidl "push = ndr_push_init_ctx(r);";
|
||||||
|
pidl "if (push == NULL) {";
|
||||||
|
pidl "\ttalloc_free(r);";
|
||||||
|
pidl "\treturn false;";
|
||||||
|
pidl "}";
|
||||||
|
pidl "";
|
||||||
|
pidl "/*";
|
||||||
|
pidl " * carry over the pointer count to the reply in case we are";
|
||||||
|
pidl " * using full pointer. See NDR specification for full pointers";
|
||||||
|
pidl " */";
|
||||||
|
pidl "push->ptr_count = pull->ptr_count;";
|
||||||
|
pidl "";
|
||||||
|
pidl "ndr_err = call->ndr_push(push, NDR_OUT, r);";
|
||||||
|
pidl "if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {";
|
||||||
|
pidl "\ttalloc_free(r);";
|
||||||
|
pidl "\treturn false;";
|
||||||
|
pidl "}";
|
||||||
|
pidl "";
|
||||||
|
pidl "p->out_data.rdata = ndr_push_blob(push);";
|
||||||
|
pidl "talloc_steal(p->mem_ctx, p->out_data.rdata.data);";
|
||||||
|
pidl "";
|
||||||
|
pidl "talloc_free(r);";
|
||||||
|
pidl "";
|
||||||
|
pidl "return true;";
|
||||||
|
deindent;
|
||||||
|
pidl "}";
|
||||||
|
pidl "";
|
||||||
|
}
|
||||||
|
|
||||||
|
sub ParseInterface($)
|
||||||
|
{
|
||||||
|
my $if = shift;
|
||||||
|
|
||||||
|
my $uif = uc($if->{NAME});
|
||||||
|
|
||||||
|
pidl_hdr "#ifndef __SRV_$uif\__";
|
||||||
|
pidl_hdr "#define __SRV_$uif\__";
|
||||||
|
|
||||||
|
foreach (@{$if->{FUNCTIONS}}) {
|
||||||
|
next if ($_->{PROPERTIES}{noopnum});
|
||||||
|
ParseFunction($if, $_);
|
||||||
|
}
|
||||||
|
|
||||||
|
pidl "";
|
||||||
|
pidl "/* Tables */";
|
||||||
|
pidl "static struct api_struct api_$if->{NAME}_cmds[] = ";
|
||||||
|
pidl "{";
|
||||||
|
indent;
|
||||||
|
|
||||||
|
foreach (@{$if->{FUNCTIONS}}) {
|
||||||
|
next if ($_->{PROPERTIES}{noopnum});
|
||||||
|
pidl "{\"" . uc($_->{NAME}) . "\", NDR_" . uc($_->{NAME}) . ", api_$_->{NAME}},";
|
||||||
|
}
|
||||||
|
|
||||||
|
deindent;
|
||||||
|
pidl "};";
|
||||||
|
|
||||||
|
pidl "";
|
||||||
|
|
||||||
|
pidl_hdr "void $if->{NAME}_get_pipe_fns(struct api_struct **fns, int *n_fns);";
|
||||||
|
pidl "void $if->{NAME}_get_pipe_fns(struct api_struct **fns, int *n_fns)";
|
||||||
|
pidl "{";
|
||||||
|
indent;
|
||||||
|
pidl "*fns = api_$if->{NAME}_cmds;";
|
||||||
|
pidl "*n_fns = sizeof(api_$if->{NAME}_cmds) / sizeof(struct api_struct);";
|
||||||
|
deindent;
|
||||||
|
pidl "}";
|
||||||
|
pidl "";
|
||||||
|
|
||||||
|
if (not has_property($if, "no_srv_register")) {
|
||||||
|
pidl_hdr "struct rpc_srv_callbacks;";
|
||||||
|
pidl_hdr "NTSTATUS rpc_$if->{NAME}_init(const struct rpc_srv_callbacks *rpc_srv_cb);";
|
||||||
|
pidl "NTSTATUS rpc_$if->{NAME}_init(const struct rpc_srv_callbacks *rpc_srv_cb)";
|
||||||
|
pidl "{";
|
||||||
|
pidl "\treturn rpc_srv_register(SMB_RPC_INTERFACE_VERSION, \"$if->{NAME}\", \"$if->{NAME}\", \&ndr_table_$if->{NAME}, api_$if->{NAME}_cmds, sizeof(api_$if->{NAME}_cmds) / sizeof(struct api_struct), rpc_srv_cb);";
|
||||||
|
pidl "}";
|
||||||
|
|
||||||
|
pidl "";
|
||||||
|
|
||||||
|
pidl_hdr "NTSTATUS rpc_$if->{NAME}_shutdown(void);";
|
||||||
|
pidl "NTSTATUS rpc_$if->{NAME}_shutdown(void)";
|
||||||
|
pidl "{";
|
||||||
|
pidl "\treturn rpc_srv_unregister(\&ndr_table_$if->{NAME});";
|
||||||
|
pidl "}";
|
||||||
|
}
|
||||||
|
pidl_hdr "#endif /* __SRV_$uif\__ */";
|
||||||
|
}
|
||||||
|
|
||||||
|
sub Parse($$$)
|
||||||
|
{
|
||||||
|
my($ndr,$header,$ndr_header) = @_;
|
||||||
|
|
||||||
|
$res = "";
|
||||||
|
$res_hdr = "";
|
||||||
|
|
||||||
|
pidl "/*";
|
||||||
|
pidl " * Unix SMB/CIFS implementation.";
|
||||||
|
pidl " * server auto-generated by pidl. DO NOT MODIFY!";
|
||||||
|
pidl " */";
|
||||||
|
pidl "";
|
||||||
|
pidl "#include \"includes.h\"";
|
||||||
|
pidl "#include \"ntdomain.h\"";
|
||||||
|
pidl "#include \"$header\"";
|
||||||
|
pidl_hdr "#include \"$ndr_header\"";
|
||||||
|
pidl "";
|
||||||
|
|
||||||
|
foreach (@$ndr) {
|
||||||
|
ParseInterface($_) if ($_->{TYPE} eq "INTERFACE");
|
||||||
|
}
|
||||||
|
|
||||||
|
return ($res, $res_hdr);
|
||||||
|
}
|
||||||
|
|
||||||
|
1;
|
133
tools/pidl/lib/Parse/Pidl/Samba4.pm
Normal file
133
tools/pidl/lib/Parse/Pidl/Samba4.pm
Normal file
|
@ -0,0 +1,133 @@
|
||||||
|
###################################################
|
||||||
|
# Common Samba4 functions
|
||||||
|
# Copyright jelmer@samba.org 2006
|
||||||
|
# released under the GNU GPL
|
||||||
|
|
||||||
|
package Parse::Pidl::Samba4;
|
||||||
|
|
||||||
|
require Exporter;
|
||||||
|
@ISA = qw(Exporter);
|
||||||
|
@EXPORT = qw(is_intree choose_header NumStars ElementStars ArrayBrackets DeclLong ArrayDynamicallyAllocated);
|
||||||
|
|
||||||
|
use Parse::Pidl::Util qw(has_property is_constant);
|
||||||
|
use Parse::Pidl::NDR qw(GetNextLevel);
|
||||||
|
use Parse::Pidl::Typelist qw(mapTypeName scalar_is_reference);
|
||||||
|
use Parse::Pidl qw(fatal error);
|
||||||
|
use strict;
|
||||||
|
|
||||||
|
use vars qw($VERSION);
|
||||||
|
$VERSION = '0.01';
|
||||||
|
|
||||||
|
|
||||||
|
# return true if we are using pidl within the samba source tree. This changes
|
||||||
|
# the names of include files, as some include files (such as ntstatus.h) have
|
||||||
|
# different paths when installed to the patch in the source tree
|
||||||
|
sub is_intree()
|
||||||
|
{
|
||||||
|
my $srcdir = $ENV{srcdir};
|
||||||
|
$srcdir = $srcdir ? "$srcdir/" : "";
|
||||||
|
return 1 if (-f "${srcdir}kdc/kdc.c");
|
||||||
|
return 1 if (-d "${srcdir}source4");
|
||||||
|
return 1 if (-f "${srcdir}include/smb.h");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Return an #include line depending on whether this build is an in-tree
|
||||||
|
# build or not.
|
||||||
|
sub choose_header($$)
|
||||||
|
{
|
||||||
|
my ($in,$out) = @_;
|
||||||
|
return "#include \"$in\"" if (is_intree());
|
||||||
|
return "#include <$out>";
|
||||||
|
}
|
||||||
|
|
||||||
|
sub ArrayDynamicallyAllocated($$)
|
||||||
|
{
|
||||||
|
my ($e, $l) = @_;
|
||||||
|
die("Not an array") unless ($l->{TYPE} eq "ARRAY");
|
||||||
|
return 0 if ($l->{IS_FIXED} and not has_property($e, "charset"));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub NumStars($;$)
|
||||||
|
{
|
||||||
|
my ($e, $d) = @_;
|
||||||
|
$d = 0 unless defined($d);
|
||||||
|
my $n = 0;
|
||||||
|
|
||||||
|
foreach my $l (@{$e->{LEVELS}}) {
|
||||||
|
next unless ($l->{TYPE} eq "POINTER");
|
||||||
|
|
||||||
|
my $nl = GetNextLevel($e, $l);
|
||||||
|
next if (defined($nl) and $nl->{TYPE} eq "ARRAY");
|
||||||
|
|
||||||
|
$n++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($n >= 1) {
|
||||||
|
$n-- if (scalar_is_reference($e->{TYPE}));
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach my $l (@{$e->{LEVELS}}) {
|
||||||
|
next unless ($l->{TYPE} eq "ARRAY");
|
||||||
|
next unless (ArrayDynamicallyAllocated($e, $l));
|
||||||
|
$n++;
|
||||||
|
}
|
||||||
|
|
||||||
|
error($e->{ORIGINAL}, "Too few pointers $n < $d") if ($n < $d);
|
||||||
|
|
||||||
|
$n -= $d;
|
||||||
|
|
||||||
|
return $n;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub ElementStars($;$)
|
||||||
|
{
|
||||||
|
my ($e, $d) = @_;
|
||||||
|
my $res = "";
|
||||||
|
my $n = 0;
|
||||||
|
|
||||||
|
$n = NumStars($e, $d);
|
||||||
|
$res .= "*" foreach (1..$n);
|
||||||
|
|
||||||
|
return $res;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub ArrayBrackets($)
|
||||||
|
{
|
||||||
|
my ($e) = @_;
|
||||||
|
my $res = "";
|
||||||
|
|
||||||
|
foreach my $l (@{$e->{LEVELS}}) {
|
||||||
|
next unless ($l->{TYPE} eq "ARRAY");
|
||||||
|
next if ArrayDynamicallyAllocated($e, $l);
|
||||||
|
$res .= "[$l->{SIZE_IS}]";
|
||||||
|
}
|
||||||
|
|
||||||
|
return $res;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub DeclLong($;$)
|
||||||
|
{
|
||||||
|
my ($e, $p) = @_;
|
||||||
|
my $res = "";
|
||||||
|
$p = "" unless defined($p);
|
||||||
|
|
||||||
|
if (has_property($e, "represent_as")) {
|
||||||
|
$res .= mapTypeName($e->{PROPERTIES}->{represent_as})." ";
|
||||||
|
} else {
|
||||||
|
if (has_property($e, "charset")) {
|
||||||
|
$res .= "const char ";
|
||||||
|
} else {
|
||||||
|
$res .= mapTypeName($e->{TYPE})." ";
|
||||||
|
}
|
||||||
|
|
||||||
|
$res .= ElementStars($e);
|
||||||
|
}
|
||||||
|
$res .= $p.$e->{NAME};
|
||||||
|
$res .= ArrayBrackets($e);
|
||||||
|
|
||||||
|
return $res;
|
||||||
|
}
|
||||||
|
|
||||||
|
1;
|
160
tools/pidl/lib/Parse/Pidl/Samba4/COM/Header.pm
Normal file
160
tools/pidl/lib/Parse/Pidl/Samba4/COM/Header.pm
Normal file
|
@ -0,0 +1,160 @@
|
||||||
|
# COM Header generation
|
||||||
|
# (C) 2005 Jelmer Vernooij <jelmer@samba.org>
|
||||||
|
|
||||||
|
package Parse::Pidl::Samba4::COM::Header;
|
||||||
|
|
||||||
|
use Parse::Pidl::Typelist qw(mapTypeName);
|
||||||
|
use Parse::Pidl::Util qw(has_property is_constant);
|
||||||
|
|
||||||
|
use vars qw($VERSION);
|
||||||
|
$VERSION = '0.01';
|
||||||
|
|
||||||
|
use strict;
|
||||||
|
|
||||||
|
sub GetArgumentProtoList($)
|
||||||
|
{
|
||||||
|
my $f = shift;
|
||||||
|
my $res = "";
|
||||||
|
|
||||||
|
foreach my $a (@{$f->{ELEMENTS}}) {
|
||||||
|
|
||||||
|
$res .= ", " . mapTypeName($a->{TYPE}) . " ";
|
||||||
|
|
||||||
|
my $l = $a->{POINTERS};
|
||||||
|
$l-- if (Parse::Pidl::Typelist::scalar_is_reference($a->{TYPE}));
|
||||||
|
foreach my $i (1..$l) {
|
||||||
|
$res .= "*";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (defined $a->{ARRAY_LEN}[0] && !is_constant($a->{ARRAY_LEN}[0]) &&
|
||||||
|
!$a->{POINTERS}) {
|
||||||
|
$res .= "*";
|
||||||
|
}
|
||||||
|
$res .= $a->{NAME};
|
||||||
|
if (defined $a->{ARRAY_LEN}[0] && is_constant($a->{ARRAY_LEN}[0])) {
|
||||||
|
$res .= "[$a->{ARRAY_LEN}[0]]";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $res;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub GetArgumentList($)
|
||||||
|
{
|
||||||
|
my $f = shift;
|
||||||
|
my $res = "";
|
||||||
|
|
||||||
|
foreach (@{$f->{ELEMENTS}}) { $res .= ", $_->{NAME}"; }
|
||||||
|
|
||||||
|
return $res;
|
||||||
|
}
|
||||||
|
|
||||||
|
#####################################################################
|
||||||
|
# generate vtable structure for COM interface
|
||||||
|
sub HeaderVTable($)
|
||||||
|
{
|
||||||
|
my $interface = shift;
|
||||||
|
my $res;
|
||||||
|
$res .= "#define " . uc($interface->{NAME}) . "_METHODS \\\n";
|
||||||
|
if (defined($interface->{BASE})) {
|
||||||
|
$res .= "\t" . uc($interface->{BASE} . "_METHODS") . "\\\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
my $data = $interface->{DATA};
|
||||||
|
foreach my $d (@{$data}) {
|
||||||
|
$res .= "\t" . mapTypeName($d->{RETURN_TYPE}) . " (*$d->{NAME}) (struct $interface->{NAME} *d, TALLOC_CTX *mem_ctx" . GetArgumentProtoList($d) . ");\\\n" if ($d->{TYPE} eq "FUNCTION");
|
||||||
|
}
|
||||||
|
$res .= "\n";
|
||||||
|
$res .= "struct $interface->{NAME}_vtable {\n";
|
||||||
|
$res .= "\tstruct GUID iid;\n";
|
||||||
|
$res .= "\t" . uc($interface->{NAME}) . "_METHODS\n";
|
||||||
|
$res .= "};\n\n";
|
||||||
|
|
||||||
|
return $res;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub ParseInterface($)
|
||||||
|
{
|
||||||
|
my $if = shift;
|
||||||
|
my $res;
|
||||||
|
|
||||||
|
$res .= "\n#ifndef _$if->{NAME}_\n";
|
||||||
|
$res .= "#define _$if->{NAME}_\n";
|
||||||
|
|
||||||
|
$res .="\n\n/* $if->{NAME} */\n";
|
||||||
|
|
||||||
|
$res .="#define COM_" . uc($if->{NAME}) . "_UUID $if->{PROPERTIES}->{uuid}\n\n";
|
||||||
|
|
||||||
|
$res .="struct $if->{NAME}_vtable;\n\n";
|
||||||
|
|
||||||
|
$res .="struct $if->{NAME} {
|
||||||
|
struct OBJREF obj;
|
||||||
|
struct com_context *ctx;
|
||||||
|
struct $if->{NAME}_vtable *vtable;
|
||||||
|
void *object_data;
|
||||||
|
};\n\n";
|
||||||
|
|
||||||
|
$res.=HeaderVTable($if);
|
||||||
|
|
||||||
|
foreach my $d (@{$if->{DATA}}) {
|
||||||
|
next if ($d->{TYPE} ne "FUNCTION");
|
||||||
|
|
||||||
|
$res .= "#define $if->{NAME}_$d->{NAME}(interface, mem_ctx" . GetArgumentList($d) . ") ";
|
||||||
|
|
||||||
|
$res .= "((interface)->vtable->$d->{NAME}(interface, mem_ctx" . GetArgumentList($d) . "))";
|
||||||
|
|
||||||
|
$res .="\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
$res .= "#endif\n";
|
||||||
|
|
||||||
|
return $res;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub ParseCoClass($)
|
||||||
|
{
|
||||||
|
my ($c) = @_;
|
||||||
|
my $res = "";
|
||||||
|
$res .= "#define CLSID_" . uc($c->{NAME}) . " $c->{PROPERTIES}->{uuid}\n";
|
||||||
|
if (has_property($c, "progid")) {
|
||||||
|
$res .= "#define PROGID_" . uc($c->{NAME}) . " $c->{PROPERTIES}->{progid}\n";
|
||||||
|
}
|
||||||
|
$res .= "\n";
|
||||||
|
return $res;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub Parse($$)
|
||||||
|
{
|
||||||
|
my ($idl,$ndr_header) = @_;
|
||||||
|
my $res = "";
|
||||||
|
my $has_obj = 0;
|
||||||
|
|
||||||
|
$res .= "#include \"librpc/gen_ndr/orpc.h\"\n" .
|
||||||
|
"#include \"$ndr_header\"\n\n";
|
||||||
|
|
||||||
|
foreach (@{$idl})
|
||||||
|
{
|
||||||
|
if ($_->{TYPE} eq "INTERFACE" && has_property($_, "object")) {
|
||||||
|
$res .="struct $_->{NAME};\n";
|
||||||
|
$has_obj = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (@{$idl})
|
||||||
|
{
|
||||||
|
if ($_->{TYPE} eq "INTERFACE" && has_property($_, "object")) {
|
||||||
|
$res.=ParseInterface($_);
|
||||||
|
$has_obj = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($_->{TYPE} eq "COCLASS") {
|
||||||
|
$res.=ParseCoClass($_);
|
||||||
|
$has_obj = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $res if ($has_obj);
|
||||||
|
return undef;
|
||||||
|
}
|
||||||
|
|
||||||
|
1;
|
225
tools/pidl/lib/Parse/Pidl/Samba4/COM/Proxy.pm
Normal file
225
tools/pidl/lib/Parse/Pidl/Samba4/COM/Proxy.pm
Normal file
|
@ -0,0 +1,225 @@
|
||||||
|
###################################################
|
||||||
|
# DCOM parser for Samba
|
||||||
|
# Basically the glue between COM and DCE/RPC with NDR
|
||||||
|
# Copyright jelmer@samba.org 2003-2005
|
||||||
|
# released under the GNU GPL
|
||||||
|
|
||||||
|
package Parse::Pidl::Samba4::COM::Proxy;
|
||||||
|
|
||||||
|
use Parse::Pidl::Samba4::COM::Header;
|
||||||
|
use Parse::Pidl::Typelist qw(mapTypeName);
|
||||||
|
use Parse::Pidl::Util qw(has_property);
|
||||||
|
|
||||||
|
use vars qw($VERSION);
|
||||||
|
$VERSION = '0.01';
|
||||||
|
|
||||||
|
use strict;
|
||||||
|
|
||||||
|
my($res);
|
||||||
|
|
||||||
|
sub ParseVTable($$)
|
||||||
|
{
|
||||||
|
my ($interface, $name) = @_;
|
||||||
|
|
||||||
|
# Generate the vtable
|
||||||
|
$res .="\tstruct $interface->{NAME}_vtable $name = {";
|
||||||
|
|
||||||
|
if (defined($interface->{BASE})) {
|
||||||
|
$res .= "\n\t\t{},";
|
||||||
|
}
|
||||||
|
|
||||||
|
my $data = $interface->{DATA};
|
||||||
|
|
||||||
|
foreach my $d (@{$data}) {
|
||||||
|
if ($d->{TYPE} eq "FUNCTION") {
|
||||||
|
$res .= "\n\t\tdcom_proxy_$interface->{NAME}_$d->{NAME}";
|
||||||
|
$res .= ",";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$res .= "\n\t};\n\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
sub ParseRegFunc($)
|
||||||
|
{
|
||||||
|
my $interface = shift;
|
||||||
|
|
||||||
|
$res .= "static NTSTATUS dcom_proxy_$interface->{NAME}_init(void)
|
||||||
|
{
|
||||||
|
struct $interface->{NAME}_vtable *proxy_vtable = talloc(talloc_autofree_context(), struct $interface->{NAME}_vtable);
|
||||||
|
";
|
||||||
|
|
||||||
|
if (defined($interface->{BASE})) {
|
||||||
|
$res.= "
|
||||||
|
struct GUID base_iid;
|
||||||
|
const void *base_vtable;
|
||||||
|
|
||||||
|
base_iid = ndr_table_$interface->{BASE}.syntax_id.uuid;
|
||||||
|
|
||||||
|
base_vtable = dcom_proxy_vtable_by_iid(&base_iid);
|
||||||
|
if (base_vtable == NULL) {
|
||||||
|
DEBUG(0, (\"No proxy registered for base interface '$interface->{BASE}'\\n\"));
|
||||||
|
return NT_STATUS_FOOBAR;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(&proxy_vtable, base_vtable, sizeof(struct $interface->{BASE}_vtable));
|
||||||
|
|
||||||
|
";
|
||||||
|
}
|
||||||
|
foreach my $x (@{$interface->{DATA}}) {
|
||||||
|
next unless ($x->{TYPE} eq "FUNCTION");
|
||||||
|
|
||||||
|
$res .= "\tproxy_vtable->$x->{NAME} = dcom_proxy_$interface->{NAME}_$x->{NAME};\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
$res.= "
|
||||||
|
proxy_vtable->iid = ndr_table_$interface->{NAME}.syntax_id.uuid;
|
||||||
|
|
||||||
|
return dcom_register_proxy((struct IUnknown_vtable *)proxy_vtable);
|
||||||
|
}\n\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
#####################################################################
|
||||||
|
# parse a function
|
||||||
|
sub ParseFunction($$)
|
||||||
|
{
|
||||||
|
my ($interface, $fn) = @_;
|
||||||
|
my $name = $fn->{NAME};
|
||||||
|
my $uname = uc $name;
|
||||||
|
|
||||||
|
my $tn = mapTypeName($fn->{RETURN_TYPE});
|
||||||
|
|
||||||
|
$res.="
|
||||||
|
static $tn dcom_proxy_$interface->{NAME}_$name(struct $interface->{NAME} *d, TALLOC_CTX *mem_ctx" . Parse::Pidl::Samba4::COM::Header::GetArgumentProtoList($fn) . ")
|
||||||
|
{
|
||||||
|
struct dcerpc_pipe *p;
|
||||||
|
NTSTATUS status = dcom_get_pipe(d, &p);
|
||||||
|
struct $name r;
|
||||||
|
struct rpc_request *req;
|
||||||
|
|
||||||
|
if (NT_STATUS_IS_ERR(status)) {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
ZERO_STRUCT(r.in.ORPCthis);
|
||||||
|
r.in.ORPCthis.version.MajorVersion = COM_MAJOR_VERSION;
|
||||||
|
r.in.ORPCthis.version.MinorVersion = COM_MINOR_VERSION;
|
||||||
|
";
|
||||||
|
|
||||||
|
# Put arguments into r
|
||||||
|
foreach my $a (@{$fn->{ELEMENTS}}) {
|
||||||
|
next unless (has_property($a, "in"));
|
||||||
|
if (Parse::Pidl::Typelist::typeIs($a->{TYPE}, "INTERFACE")) {
|
||||||
|
$res .="\tNDR_CHECK(dcom_OBJREF_from_IUnknown(mem_ctx, &r.in.$a->{NAME}.obj, $a->{NAME}));\n";
|
||||||
|
} else {
|
||||||
|
$res .= "\tr.in.$a->{NAME} = $a->{NAME};\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$res .="
|
||||||
|
if (p->conn->flags & DCERPC_DEBUG_PRINT_IN) {
|
||||||
|
NDR_PRINT_IN_DEBUG($name, &r);
|
||||||
|
}
|
||||||
|
|
||||||
|
status = dcerpc_ndr_request(p, &d->ipid, &ndr_table_$interface->{NAME}, NDR_$uname, mem_ctx, &r);
|
||||||
|
|
||||||
|
if (NT_STATUS_IS_OK(status) && (p->conn->flags & DCERPC_DEBUG_PRINT_OUT)) {
|
||||||
|
NDR_PRINT_OUT_DEBUG($name, r);
|
||||||
|
}
|
||||||
|
|
||||||
|
";
|
||||||
|
|
||||||
|
# Put r info back into arguments
|
||||||
|
foreach my $a (@{$fn->{ELEMENTS}}) {
|
||||||
|
next unless (has_property($a, "out"));
|
||||||
|
|
||||||
|
if (Parse::Pidl::Typelist::typeIs($a->{TYPE}, "INTERFACE")) {
|
||||||
|
$res .="\tNDR_CHECK(dcom_IUnknown_from_OBJREF(d->ctx, &$a->{NAME}, r.out.$a->{NAME}.obj));\n";
|
||||||
|
} else {
|
||||||
|
$res .= "\t*$a->{NAME} = r.out.$a->{NAME};\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($fn->{RETURN_TYPE} eq "NTSTATUS") {
|
||||||
|
$res .= "\tif (NT_STATUS_IS_OK(status)) status = r.out.result;\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
$res .=
|
||||||
|
"
|
||||||
|
return r.out.result;
|
||||||
|
}\n\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
#####################################################################
|
||||||
|
# parse the interface definitions
|
||||||
|
sub ParseInterface($)
|
||||||
|
{
|
||||||
|
my($interface) = shift;
|
||||||
|
my($data) = $interface->{DATA};
|
||||||
|
$res = "/* DCOM proxy for $interface->{NAME} generated by pidl */\n\n";
|
||||||
|
foreach my $d (@{$data}) {
|
||||||
|
($d->{TYPE} eq "FUNCTION") &&
|
||||||
|
ParseFunction($interface, $d);
|
||||||
|
}
|
||||||
|
|
||||||
|
ParseRegFunc($interface);
|
||||||
|
}
|
||||||
|
|
||||||
|
sub RegistrationFunction($$)
|
||||||
|
{
|
||||||
|
my $idl = shift;
|
||||||
|
my $basename = shift;
|
||||||
|
|
||||||
|
my $res = "\n\nNTSTATUS dcom_$basename\_init(void)\n";
|
||||||
|
$res .= "{\n";
|
||||||
|
$res .="\tNTSTATUS status = NT_STATUS_OK;\n";
|
||||||
|
foreach my $interface (@{$idl}) {
|
||||||
|
next if $interface->{TYPE} ne "INTERFACE";
|
||||||
|
next if not has_property($interface, "object");
|
||||||
|
|
||||||
|
my $data = $interface->{DATA};
|
||||||
|
my $count = 0;
|
||||||
|
foreach my $d (@{$data}) {
|
||||||
|
if ($d->{TYPE} eq "FUNCTION") { $count++; }
|
||||||
|
}
|
||||||
|
|
||||||
|
next if ($count == 0);
|
||||||
|
|
||||||
|
$res .= "\tstatus = dcom_$interface->{NAME}_init();\n";
|
||||||
|
$res .= "\tif (NT_STATUS_IS_ERR(status)) {\n";
|
||||||
|
$res .= "\t\treturn status;\n";
|
||||||
|
$res .= "\t}\n\n";
|
||||||
|
}
|
||||||
|
$res .= "\treturn status;\n";
|
||||||
|
$res .= "}\n\n";
|
||||||
|
|
||||||
|
return $res;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub Parse($$)
|
||||||
|
{
|
||||||
|
my ($pidl,$comh_filename) = @_;
|
||||||
|
my $res = "";
|
||||||
|
my $has_obj = 0;
|
||||||
|
|
||||||
|
$res .= "#include \"includes.h\"\n" .
|
||||||
|
"#include \"lib/com/dcom/dcom.h\"\n" .
|
||||||
|
"#include \"$comh_filename\"\n" .
|
||||||
|
"#include \"librpc/rpc/dcerpc.h\"\n";
|
||||||
|
|
||||||
|
foreach (@{$pidl}) {
|
||||||
|
next if ($_->{TYPE} ne "INTERFACE");
|
||||||
|
next if has_property($_, "local");
|
||||||
|
next unless has_property($_, "object");
|
||||||
|
|
||||||
|
$res .= ParseInterface($_);
|
||||||
|
|
||||||
|
$has_obj = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $res if ($has_obj);
|
||||||
|
return undef;
|
||||||
|
}
|
||||||
|
|
||||||
|
1;
|
327
tools/pidl/lib/Parse/Pidl/Samba4/COM/Stub.pm
Normal file
327
tools/pidl/lib/Parse/Pidl/Samba4/COM/Stub.pm
Normal file
|
@ -0,0 +1,327 @@
|
||||||
|
###################################################
|
||||||
|
# DCOM stub boilerplate generator
|
||||||
|
# Copyright jelmer@samba.org 2004-2005
|
||||||
|
# Copyright tridge@samba.org 2003
|
||||||
|
# Copyright metze@samba.org 2004
|
||||||
|
# released under the GNU GPL
|
||||||
|
|
||||||
|
package Parse::Pidl::Samba4::COM::Stub;
|
||||||
|
|
||||||
|
use Parse::Pidl::Util qw(has_property);
|
||||||
|
use strict;
|
||||||
|
|
||||||
|
use vars qw($VERSION);
|
||||||
|
$VERSION = '0.01';
|
||||||
|
|
||||||
|
my($res);
|
||||||
|
|
||||||
|
sub pidl($)
|
||||||
|
{
|
||||||
|
$res .= shift;
|
||||||
|
}
|
||||||
|
|
||||||
|
#####################################################
|
||||||
|
# generate the switch statement for function dispatch
|
||||||
|
sub gen_dispatch_switch($)
|
||||||
|
{
|
||||||
|
my $data = shift;
|
||||||
|
|
||||||
|
my $count = 0;
|
||||||
|
foreach my $d (@{$data}) {
|
||||||
|
next if ($d->{TYPE} ne "FUNCTION");
|
||||||
|
|
||||||
|
pidl "\tcase $count: {\n";
|
||||||
|
if ($d->{RETURN_TYPE} && $d->{RETURN_TYPE} ne "void") {
|
||||||
|
pidl "\t\tNTSTATUS result;\n";
|
||||||
|
}
|
||||||
|
pidl "\t\tstruct $d->{NAME} *r2 = r;\n";
|
||||||
|
pidl "\t\tif (DEBUGLEVEL > 10) {\n";
|
||||||
|
pidl "\t\t\tNDR_PRINT_FUNCTION_DEBUG($d->{NAME}, NDR_IN, r2);\n";
|
||||||
|
pidl "\t\t}\n";
|
||||||
|
if ($d->{RETURN_TYPE} && $d->{RETURN_TYPE} ne "void") {
|
||||||
|
pidl "\t\tresult = vtable->$d->{NAME}(iface, mem_ctx, r2);\n";
|
||||||
|
} else {
|
||||||
|
pidl "\t\tvtable->$d->{NAME}(iface, mem_ctx, r2);\n";
|
||||||
|
}
|
||||||
|
pidl "\t\tif (dce_call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {\n";
|
||||||
|
pidl "\t\t\tDEBUG(5,(\"function $d->{NAME} will reply async\\n\"));\n";
|
||||||
|
pidl "\t\t}\n";
|
||||||
|
pidl "\t\tbreak;\n\t}\n";
|
||||||
|
$count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#####################################################
|
||||||
|
# generate the switch statement for function reply
|
||||||
|
sub gen_reply_switch($)
|
||||||
|
{
|
||||||
|
my $data = shift;
|
||||||
|
|
||||||
|
my $count = 0;
|
||||||
|
foreach my $d (@{$data}) {
|
||||||
|
next if ($d->{TYPE} ne "FUNCTION");
|
||||||
|
|
||||||
|
pidl "\tcase $count: {\n";
|
||||||
|
pidl "\t\tstruct $d->{NAME} *r2 = r;\n";
|
||||||
|
pidl "\t\tif (dce_call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {\n";
|
||||||
|
pidl "\t\t\tDEBUG(5,(\"function $d->{NAME} replied async\\n\"));\n";
|
||||||
|
pidl "\t\t}\n";
|
||||||
|
pidl "\t\tif (DEBUGLEVEL > 10 && dce_call->fault_code == 0) {\n";
|
||||||
|
pidl "\t\t\tNDR_PRINT_FUNCTION_DEBUG($d->{NAME}, NDR_OUT | NDR_SET_VALUES, r2);\n";
|
||||||
|
pidl "\t\t}\n";
|
||||||
|
pidl "\t\tif (dce_call->fault_code != 0) {\n";
|
||||||
|
pidl "\t\t\tDEBUG(2,(\"dcerpc_fault %s in $d->{NAME}\\n\", dcerpc_errstr(mem_ctx, dce_call->fault_code)));\n";
|
||||||
|
pidl "\t\t}\n";
|
||||||
|
pidl "\t\tbreak;\n\t}\n";
|
||||||
|
$count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#####################################################################
|
||||||
|
# produce boilerplate code for a interface
|
||||||
|
sub Boilerplate_Iface($)
|
||||||
|
{
|
||||||
|
my($interface) = shift;
|
||||||
|
my($data) = $interface->{DATA};
|
||||||
|
my $name = $interface->{NAME};
|
||||||
|
my $uname = uc $name;
|
||||||
|
my $uuid = Parse::Pidl::Util::make_str($interface->{PROPERTIES}->{uuid});
|
||||||
|
my $if_version = $interface->{PROPERTIES}->{version};
|
||||||
|
|
||||||
|
pidl "
|
||||||
|
static NTSTATUS $name\__op_bind(struct dcesrv_call_state *dce_call, const struct dcesrv_interface *iface, uint32_t if_version)
|
||||||
|
{
|
||||||
|
#ifdef DCESRV_INTERFACE_$uname\_BIND
|
||||||
|
return DCESRV_INTERFACE_$uname\_BIND(dce_call,iface);
|
||||||
|
#else
|
||||||
|
return NT_STATUS_OK;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static void $name\__op_unbind(struct dcesrv_connection_context *context, const struct dcesrv_interface *iface)
|
||||||
|
{
|
||||||
|
#ifdef DCESRV_INTERFACE_$uname\_UNBIND
|
||||||
|
DCESRV_INTERFACE_$uname\_UNBIND(context, iface);
|
||||||
|
#else
|
||||||
|
return;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static NTSTATUS $name\__op_ndr_pull(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct ndr_pull *pull, void **r)
|
||||||
|
{
|
||||||
|
NTSTATUS status;
|
||||||
|
uint16_t opnum = dce_call->pkt.u.request.opnum;
|
||||||
|
|
||||||
|
dce_call->fault_code = 0;
|
||||||
|
|
||||||
|
if (opnum >= dcerpc_table_$name.num_calls) {
|
||||||
|
dce_call->fault_code = DCERPC_FAULT_OP_RNG_ERROR;
|
||||||
|
return NT_STATUS_NET_WRITE_FAULT;
|
||||||
|
}
|
||||||
|
|
||||||
|
*r = talloc_size(mem_ctx, dcerpc_table_$name.calls[opnum].struct_size);
|
||||||
|
NT_STATUS_HAVE_NO_MEMORY(*r);
|
||||||
|
|
||||||
|
/* unravel the NDR for the packet */
|
||||||
|
status = dcerpc_table_$name.calls[opnum].ndr_pull(pull, NDR_IN, *r);
|
||||||
|
if (!NT_STATUS_IS_OK(status)) {
|
||||||
|
dcerpc_log_packet(&dcerpc_table_$name, opnum, NDR_IN,
|
||||||
|
&dce_call->pkt.u.request.stub_and_verifier);
|
||||||
|
dce_call->fault_code = DCERPC_FAULT_NDR;
|
||||||
|
return NT_STATUS_NET_WRITE_FAULT;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NT_STATUS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static NTSTATUS $name\__op_dispatch(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, void *r)
|
||||||
|
{
|
||||||
|
uint16_t opnum = dce_call->pkt.u.request.opnum;
|
||||||
|
struct GUID ipid = dce_call->pkt.u.request.object.object;
|
||||||
|
struct dcom_interface_p *iface = dcom_get_local_iface_p(&ipid);
|
||||||
|
const struct dcom_$name\_vtable *vtable = iface->vtable;
|
||||||
|
|
||||||
|
switch (opnum) {
|
||||||
|
";
|
||||||
|
gen_dispatch_switch($data);
|
||||||
|
|
||||||
|
pidl "
|
||||||
|
default:
|
||||||
|
dce_call->fault_code = DCERPC_FAULT_OP_RNG_ERROR;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dce_call->fault_code != 0) {
|
||||||
|
dcerpc_log_packet(&dcerpc_table_$name, opnum, NDR_IN,
|
||||||
|
&dce_call->pkt.u.request.stub_and_verifier);
|
||||||
|
return NT_STATUS_NET_WRITE_FAULT;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NT_STATUS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static NTSTATUS $name\__op_reply(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, void *r)
|
||||||
|
{
|
||||||
|
uint16_t opnum = dce_call->pkt.u.request.opnum;
|
||||||
|
|
||||||
|
switch (opnum) {
|
||||||
|
";
|
||||||
|
gen_reply_switch($data);
|
||||||
|
|
||||||
|
pidl "
|
||||||
|
default:
|
||||||
|
dce_call->fault_code = DCERPC_FAULT_OP_RNG_ERROR;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dce_call->fault_code != 0) {
|
||||||
|
dcerpc_log_packet(&dcerpc_table_$name, opnum, NDR_IN,
|
||||||
|
&dce_call->pkt.u.request.stub_and_verifier);
|
||||||
|
return NT_STATUS_NET_WRITE_FAULT;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NT_STATUS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static NTSTATUS $name\__op_ndr_push(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct ndr_push *push, const void *r)
|
||||||
|
{
|
||||||
|
NTSTATUS status;
|
||||||
|
uint16_t opnum = dce_call->pkt.u.request.opnum;
|
||||||
|
|
||||||
|
status = dcerpc_table_$name.calls[opnum].ndr_push(push, NDR_OUT, r);
|
||||||
|
if (!NT_STATUS_IS_OK(status)) {
|
||||||
|
dce_call->fault_code = DCERPC_FAULT_NDR;
|
||||||
|
return NT_STATUS_NET_WRITE_FAULT;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NT_STATUS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct dcesrv_interface $name\_interface = {
|
||||||
|
.name = \"$name\",
|
||||||
|
.uuid = $uuid,
|
||||||
|
.if_version = $if_version,
|
||||||
|
.bind = $name\__op_bind,
|
||||||
|
.unbind = $name\__op_unbind,
|
||||||
|
.ndr_pull = $name\__op_ndr_pull,
|
||||||
|
.dispatch = $name\__op_dispatch,
|
||||||
|
.reply = $name\__op_reply,
|
||||||
|
.ndr_push = $name\__op_ndr_push
|
||||||
|
};
|
||||||
|
|
||||||
|
";
|
||||||
|
}
|
||||||
|
|
||||||
|
#####################################################################
|
||||||
|
# produce boilerplate code for an endpoint server
|
||||||
|
sub Boilerplate_Ep_Server($)
|
||||||
|
{
|
||||||
|
my($interface) = shift;
|
||||||
|
my $name = $interface->{NAME};
|
||||||
|
my $uname = uc $name;
|
||||||
|
|
||||||
|
pidl "
|
||||||
|
static NTSTATUS $name\__op_init_server(struct dcesrv_context *dce_ctx, const struct dcesrv_endpoint_server *ep_server)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i=0;i<dcerpc_table_$name.endpoints->count;i++) {
|
||||||
|
NTSTATUS ret;
|
||||||
|
const char *name = dcerpc_table_$name.endpoints->names[i];
|
||||||
|
|
||||||
|
ret = dcesrv_interface_register(dce_ctx, name, &$name\_interface, NULL);
|
||||||
|
if (!NT_STATUS_IS_OK(ret)) {
|
||||||
|
DEBUG(1,(\"$name\_op_init_server: failed to register endpoint \'%s\'\\n\",name));
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NT_STATUS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static BOOL $name\__op_interface_by_uuid(struct dcesrv_interface *iface, const char *uuid, uint32_t if_version)
|
||||||
|
{
|
||||||
|
if (dcerpc_table_$name.if_version == if_version &&
|
||||||
|
strcmp(dcerpc_table_$name.uuid, uuid)==0) {
|
||||||
|
memcpy(iface,&dcerpc_table_$name, sizeof(*iface));
|
||||||
|
return True;
|
||||||
|
}
|
||||||
|
|
||||||
|
return False;
|
||||||
|
}
|
||||||
|
|
||||||
|
static BOOL $name\__op_interface_by_name(struct dcesrv_interface *iface, const char *name)
|
||||||
|
{
|
||||||
|
if (strcmp(dcerpc_table_$name.name, name)==0) {
|
||||||
|
memcpy(iface,&dcerpc_table_$name, sizeof(*iface));
|
||||||
|
return True;
|
||||||
|
}
|
||||||
|
|
||||||
|
return False;
|
||||||
|
}
|
||||||
|
|
||||||
|
NTSTATUS dcerpc_server_$name\_init(void)
|
||||||
|
{
|
||||||
|
NTSTATUS ret;
|
||||||
|
struct dcesrv_endpoint_server ep_server;
|
||||||
|
|
||||||
|
/* fill in our name */
|
||||||
|
ep_server.name = \"$name\";
|
||||||
|
|
||||||
|
/* fill in all the operations */
|
||||||
|
ep_server.init_server = $name\__op_init_server;
|
||||||
|
|
||||||
|
ep_server.interface_by_uuid = $name\__op_interface_by_uuid;
|
||||||
|
ep_server.interface_by_name = $name\__op_interface_by_name;
|
||||||
|
|
||||||
|
/* register ourselves with the DCERPC subsystem. */
|
||||||
|
ret = dcerpc_register_ep_server(&ep_server);
|
||||||
|
|
||||||
|
if (!NT_STATUS_IS_OK(ret)) {
|
||||||
|
DEBUG(0,(\"Failed to register \'$name\' endpoint server!\\n\"));
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
";
|
||||||
|
}
|
||||||
|
|
||||||
|
#####################################################################
|
||||||
|
# dcom interface stub from a parsed IDL structure
|
||||||
|
sub ParseInterface($)
|
||||||
|
{
|
||||||
|
my($interface) = shift;
|
||||||
|
|
||||||
|
return "" if has_property($interface, "local");
|
||||||
|
|
||||||
|
my($data) = $interface->{DATA};
|
||||||
|
my $count = 0;
|
||||||
|
|
||||||
|
$res = "";
|
||||||
|
|
||||||
|
if (!defined $interface->{PROPERTIES}->{uuid}) {
|
||||||
|
return $res;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!defined $interface->{PROPERTIES}->{version}) {
|
||||||
|
$interface->{PROPERTIES}->{version} = "0.0";
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach my $d (@{$data}) {
|
||||||
|
if ($d->{TYPE} eq "FUNCTION") { $count++; }
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($count == 0) {
|
||||||
|
return $res;
|
||||||
|
}
|
||||||
|
|
||||||
|
$res = "/* dcom interface stub generated by pidl */\n\n";
|
||||||
|
Boilerplate_Iface($interface);
|
||||||
|
Boilerplate_Ep_Server($interface);
|
||||||
|
|
||||||
|
return $res;
|
||||||
|
}
|
||||||
|
|
||||||
|
1;
|
537
tools/pidl/lib/Parse/Pidl/Samba4/Header.pm
Normal file
537
tools/pidl/lib/Parse/Pidl/Samba4/Header.pm
Normal file
|
@ -0,0 +1,537 @@
|
||||||
|
###################################################
|
||||||
|
# create C header files for an IDL structure
|
||||||
|
# Copyright tridge@samba.org 2000
|
||||||
|
# Copyright jelmer@samba.org 2005
|
||||||
|
# released under the GNU GPL
|
||||||
|
|
||||||
|
package Parse::Pidl::Samba4::Header;
|
||||||
|
require Exporter;
|
||||||
|
|
||||||
|
@ISA = qw(Exporter);
|
||||||
|
@EXPORT_OK = qw(GenerateFunctionInEnv GenerateFunctionOutEnv EnvSubstituteValue GenerateStructEnv);
|
||||||
|
|
||||||
|
use strict;
|
||||||
|
use Parse::Pidl qw(fatal);
|
||||||
|
use Parse::Pidl::Typelist qw(mapTypeName scalar_is_reference);
|
||||||
|
use Parse::Pidl::Util qw(has_property is_constant unmake_str ParseExpr);
|
||||||
|
use Parse::Pidl::Samba4 qw(is_intree ElementStars ArrayBrackets choose_header);
|
||||||
|
|
||||||
|
use vars qw($VERSION);
|
||||||
|
$VERSION = '0.01';
|
||||||
|
|
||||||
|
my($res);
|
||||||
|
my($tab_depth);
|
||||||
|
|
||||||
|
sub pidl($) { $res .= shift; }
|
||||||
|
|
||||||
|
sub tabs()
|
||||||
|
{
|
||||||
|
my $res = "";
|
||||||
|
$res .="\t" foreach (1..$tab_depth);
|
||||||
|
return $res;
|
||||||
|
}
|
||||||
|
|
||||||
|
#####################################################################
|
||||||
|
# parse a properties list
|
||||||
|
sub HeaderProperties($$)
|
||||||
|
{
|
||||||
|
my($props,$ignores) = @_;
|
||||||
|
my $ret = "";
|
||||||
|
|
||||||
|
foreach my $d (keys %{$props}) {
|
||||||
|
next if (grep(/^$d$/, @$ignores));
|
||||||
|
if($props->{$d} ne "1") {
|
||||||
|
$ret.= "$d($props->{$d}),";
|
||||||
|
} else {
|
||||||
|
$ret.="$d,";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($ret) {
|
||||||
|
pidl "/* [" . substr($ret, 0, -1) . "] */";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#####################################################################
|
||||||
|
# parse a structure element
|
||||||
|
sub HeaderElement($)
|
||||||
|
{
|
||||||
|
my($element) = shift;
|
||||||
|
|
||||||
|
pidl tabs();
|
||||||
|
if (has_property($element, "represent_as")) {
|
||||||
|
pidl mapTypeName($element->{PROPERTIES}->{represent_as})." ";
|
||||||
|
} else {
|
||||||
|
if (ref($element->{TYPE}) eq "HASH") {
|
||||||
|
HeaderType($element, $element->{TYPE}, $element->{TYPE}->{NAME});
|
||||||
|
} else {
|
||||||
|
HeaderType($element, $element->{TYPE}, "");
|
||||||
|
}
|
||||||
|
pidl " ".ElementStars($element);
|
||||||
|
}
|
||||||
|
pidl $element->{NAME};
|
||||||
|
pidl ArrayBrackets($element);
|
||||||
|
|
||||||
|
pidl ";";
|
||||||
|
if (defined $element->{PROPERTIES}) {
|
||||||
|
HeaderProperties($element->{PROPERTIES}, ["in", "out"]);
|
||||||
|
}
|
||||||
|
pidl "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
#####################################################################
|
||||||
|
# parse a struct
|
||||||
|
sub HeaderStruct($$;$)
|
||||||
|
{
|
||||||
|
my($struct,$name,$tail) = @_;
|
||||||
|
pidl "struct $name";
|
||||||
|
pidl $tail if defined($tail) and not defined($struct->{ELEMENTS});
|
||||||
|
return if (not defined($struct->{ELEMENTS}));
|
||||||
|
pidl " {\n";
|
||||||
|
$tab_depth++;
|
||||||
|
my $el_count=0;
|
||||||
|
foreach (@{$struct->{ELEMENTS}}) {
|
||||||
|
HeaderElement($_);
|
||||||
|
$el_count++;
|
||||||
|
}
|
||||||
|
if ($el_count == 0) {
|
||||||
|
# some compilers can't handle empty structures
|
||||||
|
pidl tabs()."char _empty_;\n";
|
||||||
|
}
|
||||||
|
$tab_depth--;
|
||||||
|
pidl tabs()."}";
|
||||||
|
if (defined $struct->{PROPERTIES}) {
|
||||||
|
HeaderProperties($struct->{PROPERTIES}, []);
|
||||||
|
}
|
||||||
|
pidl $tail if defined($tail);
|
||||||
|
}
|
||||||
|
|
||||||
|
#####################################################################
|
||||||
|
# parse a enum
|
||||||
|
sub HeaderEnum($$;$)
|
||||||
|
{
|
||||||
|
my($enum,$name,$tail) = @_;
|
||||||
|
my $first = 1;
|
||||||
|
|
||||||
|
pidl "enum $name";
|
||||||
|
if (defined($enum->{ELEMENTS})) {
|
||||||
|
pidl "\n#ifndef USE_UINT_ENUMS\n";
|
||||||
|
pidl " {\n";
|
||||||
|
$tab_depth++;
|
||||||
|
foreach my $e (@{$enum->{ELEMENTS}}) {
|
||||||
|
my @enum_els = ();
|
||||||
|
unless ($first) { pidl ",\n"; }
|
||||||
|
$first = 0;
|
||||||
|
pidl tabs();
|
||||||
|
@enum_els = split(/=/, $e);
|
||||||
|
if (@enum_els == 2) {
|
||||||
|
pidl $enum_els[0];
|
||||||
|
pidl "=(int)";
|
||||||
|
pidl "(";
|
||||||
|
pidl $enum_els[1];
|
||||||
|
pidl ")";
|
||||||
|
} else {
|
||||||
|
pidl $e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pidl "\n";
|
||||||
|
$tab_depth--;
|
||||||
|
pidl "}";
|
||||||
|
pidl "\n";
|
||||||
|
pidl "#else\n";
|
||||||
|
my $count = 0;
|
||||||
|
my $with_val = 0;
|
||||||
|
my $without_val = 0;
|
||||||
|
pidl " { __do_not_use_enum_$name=0x7FFFFFFF}\n";
|
||||||
|
foreach my $e (@{$enum->{ELEMENTS}}) {
|
||||||
|
my $t = "$e";
|
||||||
|
my $name;
|
||||||
|
my $value;
|
||||||
|
if ($t =~ /(.*)=(.*)/) {
|
||||||
|
$name = $1;
|
||||||
|
$value = $2;
|
||||||
|
$with_val = 1;
|
||||||
|
fatal($e->{ORIGINAL}, "you can't mix enum member with values and without values!")
|
||||||
|
unless ($without_val == 0);
|
||||||
|
} else {
|
||||||
|
$name = $t;
|
||||||
|
$value = $count++;
|
||||||
|
$without_val = 1;
|
||||||
|
fatal($e->{ORIGINAL}, "you can't mix enum member with values and without values!")
|
||||||
|
unless ($with_val == 0);
|
||||||
|
}
|
||||||
|
pidl "#define $name ( $value )\n";
|
||||||
|
}
|
||||||
|
pidl "#endif\n";
|
||||||
|
}
|
||||||
|
pidl $tail if defined($tail);
|
||||||
|
}
|
||||||
|
|
||||||
|
#####################################################################
|
||||||
|
# parse a bitmap
|
||||||
|
sub HeaderBitmap($$)
|
||||||
|
{
|
||||||
|
my($bitmap,$name) = @_;
|
||||||
|
|
||||||
|
return unless defined($bitmap->{ELEMENTS});
|
||||||
|
|
||||||
|
pidl "/* bitmap $name */\n";
|
||||||
|
pidl "#define $_\n" foreach (@{$bitmap->{ELEMENTS}});
|
||||||
|
pidl "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
#####################################################################
|
||||||
|
# parse a union
|
||||||
|
sub HeaderUnion($$;$)
|
||||||
|
{
|
||||||
|
my($union,$name,$tail) = @_;
|
||||||
|
my %done = ();
|
||||||
|
|
||||||
|
pidl "union $name";
|
||||||
|
pidl $tail if defined($tail) and not defined($union->{ELEMENTS});
|
||||||
|
return if (not defined($union->{ELEMENTS}));
|
||||||
|
pidl " {\n";
|
||||||
|
$tab_depth++;
|
||||||
|
my $needed = 0;
|
||||||
|
foreach my $e (@{$union->{ELEMENTS}}) {
|
||||||
|
if ($e->{TYPE} ne "EMPTY") {
|
||||||
|
if (! defined $done{$e->{NAME}}) {
|
||||||
|
HeaderElement($e);
|
||||||
|
}
|
||||||
|
$done{$e->{NAME}} = 1;
|
||||||
|
$needed++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!$needed) {
|
||||||
|
# sigh - some compilers don't like empty structures
|
||||||
|
pidl tabs()."int _dummy_element;\n";
|
||||||
|
}
|
||||||
|
$tab_depth--;
|
||||||
|
pidl "}";
|
||||||
|
|
||||||
|
if (defined $union->{PROPERTIES}) {
|
||||||
|
HeaderProperties($union->{PROPERTIES}, []);
|
||||||
|
}
|
||||||
|
pidl $tail if defined($tail);
|
||||||
|
}
|
||||||
|
|
||||||
|
#####################################################################
|
||||||
|
# parse a pipe
|
||||||
|
sub HeaderPipe($$;$)
|
||||||
|
{
|
||||||
|
my($pipe,$name,$tail) = @_;
|
||||||
|
|
||||||
|
my $struct = $pipe->{DATA};
|
||||||
|
my $e = $struct->{ELEMENTS}[1];
|
||||||
|
|
||||||
|
pidl "struct $name;\n";
|
||||||
|
pidl "struct $struct->{NAME} {\n";
|
||||||
|
$tab_depth++;
|
||||||
|
pidl tabs()."uint32_t count;\n";
|
||||||
|
pidl tabs().mapTypeName($e->{TYPE})." *array;\n";
|
||||||
|
$tab_depth--;
|
||||||
|
pidl "}";
|
||||||
|
|
||||||
|
if (defined $struct->{PROPERTIES}) {
|
||||||
|
HeaderProperties($struct->{PROPERTIES}, []);
|
||||||
|
}
|
||||||
|
|
||||||
|
pidl $tail if defined($tail);
|
||||||
|
}
|
||||||
|
|
||||||
|
#####################################################################
|
||||||
|
# parse a type
|
||||||
|
sub HeaderType($$$;$)
|
||||||
|
{
|
||||||
|
my($e,$data,$name,$tail) = @_;
|
||||||
|
if (ref($data) eq "HASH") {
|
||||||
|
($data->{TYPE} eq "ENUM") && HeaderEnum($data, $name, $tail);
|
||||||
|
($data->{TYPE} eq "BITMAP") && HeaderBitmap($data, $name);
|
||||||
|
($data->{TYPE} eq "STRUCT") && HeaderStruct($data, $name, $tail);
|
||||||
|
($data->{TYPE} eq "UNION") && HeaderUnion($data, $name, $tail);
|
||||||
|
($data->{TYPE} eq "PIPE") && HeaderPipe($data, $name, $tail);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (has_property($e, "charset")) {
|
||||||
|
pidl "const char";
|
||||||
|
} else {
|
||||||
|
pidl mapTypeName($e->{TYPE});
|
||||||
|
}
|
||||||
|
pidl $tail if defined($tail);
|
||||||
|
}
|
||||||
|
|
||||||
|
#####################################################################
|
||||||
|
# parse a typedef
|
||||||
|
sub HeaderTypedef($;$)
|
||||||
|
{
|
||||||
|
my($typedef,$tail) = @_;
|
||||||
|
# Don't print empty "enum foo;", since some compilers don't like it.
|
||||||
|
return if ($typedef->{DATA}->{TYPE} eq "ENUM" and not defined($typedef->{DATA}->{ELEMENTS}));
|
||||||
|
HeaderType($typedef, $typedef->{DATA}, $typedef->{NAME}, $tail) if defined ($typedef->{DATA});
|
||||||
|
}
|
||||||
|
|
||||||
|
#####################################################################
|
||||||
|
# parse a const
|
||||||
|
sub HeaderConst($)
|
||||||
|
{
|
||||||
|
my($const) = shift;
|
||||||
|
if (!defined($const->{ARRAY_LEN}[0])) {
|
||||||
|
pidl "#define $const->{NAME}\t( $const->{VALUE} )\n";
|
||||||
|
} else {
|
||||||
|
pidl "#define $const->{NAME}\t $const->{VALUE}\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sub ElementDirection($)
|
||||||
|
{
|
||||||
|
my ($e) = @_;
|
||||||
|
|
||||||
|
return "inout" if (has_property($e, "in") and has_property($e, "out"));
|
||||||
|
return "in" if (has_property($e, "in"));
|
||||||
|
return "out" if (has_property($e, "out"));
|
||||||
|
return "inout";
|
||||||
|
}
|
||||||
|
|
||||||
|
#####################################################################
|
||||||
|
# parse a function
|
||||||
|
sub HeaderFunctionInOut($$)
|
||||||
|
{
|
||||||
|
my($fn,$prop) = @_;
|
||||||
|
|
||||||
|
return unless defined($fn->{ELEMENTS});
|
||||||
|
|
||||||
|
foreach my $e (@{$fn->{ELEMENTS}}) {
|
||||||
|
HeaderElement($e) if (ElementDirection($e) eq $prop);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#####################################################################
|
||||||
|
# determine if we need an "in" or "out" section
|
||||||
|
sub HeaderFunctionInOut_needed($$)
|
||||||
|
{
|
||||||
|
my($fn,$prop) = @_;
|
||||||
|
|
||||||
|
return 1 if ($prop eq "out" && defined($fn->{RETURN_TYPE}));
|
||||||
|
|
||||||
|
return undef unless defined($fn->{ELEMENTS});
|
||||||
|
|
||||||
|
foreach my $e (@{$fn->{ELEMENTS}}) {
|
||||||
|
return 1 if (ElementDirection($e) eq $prop);
|
||||||
|
}
|
||||||
|
|
||||||
|
return undef;
|
||||||
|
}
|
||||||
|
|
||||||
|
my %headerstructs;
|
||||||
|
|
||||||
|
#####################################################################
|
||||||
|
# parse a function
|
||||||
|
sub HeaderFunction($)
|
||||||
|
{
|
||||||
|
my($fn) = shift;
|
||||||
|
|
||||||
|
return if ($headerstructs{$fn->{NAME}});
|
||||||
|
|
||||||
|
$headerstructs{$fn->{NAME}} = 1;
|
||||||
|
|
||||||
|
pidl "\nstruct $fn->{NAME} {\n";
|
||||||
|
$tab_depth++;
|
||||||
|
my $needed = 0;
|
||||||
|
|
||||||
|
if (HeaderFunctionInOut_needed($fn, "in") or
|
||||||
|
HeaderFunctionInOut_needed($fn, "inout")) {
|
||||||
|
pidl tabs()."struct {\n";
|
||||||
|
$tab_depth++;
|
||||||
|
HeaderFunctionInOut($fn, "in");
|
||||||
|
HeaderFunctionInOut($fn, "inout");
|
||||||
|
$tab_depth--;
|
||||||
|
pidl tabs()."} in;\n\n";
|
||||||
|
$needed++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (HeaderFunctionInOut_needed($fn, "out") or
|
||||||
|
HeaderFunctionInOut_needed($fn, "inout")) {
|
||||||
|
pidl tabs()."struct {\n";
|
||||||
|
$tab_depth++;
|
||||||
|
HeaderFunctionInOut($fn, "out");
|
||||||
|
HeaderFunctionInOut($fn, "inout");
|
||||||
|
if (defined($fn->{RETURN_TYPE})) {
|
||||||
|
pidl tabs().mapTypeName($fn->{RETURN_TYPE}) . " result;\n";
|
||||||
|
}
|
||||||
|
$tab_depth--;
|
||||||
|
pidl tabs()."} out;\n\n";
|
||||||
|
$needed++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$needed) {
|
||||||
|
# sigh - some compilers don't like empty structures
|
||||||
|
pidl tabs()."int _dummy_element;\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
$tab_depth--;
|
||||||
|
pidl "};\n\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
sub HeaderImport
|
||||||
|
{
|
||||||
|
my @imports = @_;
|
||||||
|
foreach my $import (@imports) {
|
||||||
|
$import = unmake_str($import);
|
||||||
|
$import =~ s/\.idl$//;
|
||||||
|
pidl choose_header("librpc/gen_ndr/$import\.h", "gen_ndr/$import.h") . "\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sub HeaderInclude
|
||||||
|
{
|
||||||
|
my @includes = @_;
|
||||||
|
foreach (@includes) {
|
||||||
|
pidl "#include $_\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#####################################################################
|
||||||
|
# parse the interface definitions
|
||||||
|
sub HeaderInterface($)
|
||||||
|
{
|
||||||
|
my($interface) = shift;
|
||||||
|
|
||||||
|
pidl "#ifndef _HEADER_$interface->{NAME}\n";
|
||||||
|
pidl "#define _HEADER_$interface->{NAME}\n\n";
|
||||||
|
|
||||||
|
foreach my $c (@{$interface->{CONSTS}}) {
|
||||||
|
HeaderConst($c);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach my $t (@{$interface->{TYPES}}) {
|
||||||
|
HeaderTypedef($t, ";\n\n") if ($t->{TYPE} eq "TYPEDEF");
|
||||||
|
HeaderStruct($t, $t->{NAME}, ";\n\n") if ($t->{TYPE} eq "STRUCT");
|
||||||
|
HeaderUnion($t, $t->{NAME}, ";\n\n") if ($t->{TYPE} eq "UNION");
|
||||||
|
HeaderEnum($t, $t->{NAME}, ";\n\n") if ($t->{TYPE} eq "ENUM");
|
||||||
|
HeaderBitmap($t, $t->{NAME}) if ($t->{TYPE} eq "BITMAP");
|
||||||
|
HeaderPipe($t, $t->{NAME}, "\n\n") if ($t->{TYPE} eq "PIPE");
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach my $fn (@{$interface->{FUNCTIONS}}) {
|
||||||
|
HeaderFunction($fn);
|
||||||
|
}
|
||||||
|
|
||||||
|
pidl "#endif /* _HEADER_$interface->{NAME} */\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
sub HeaderQuote($)
|
||||||
|
{
|
||||||
|
my($quote) = shift;
|
||||||
|
|
||||||
|
pidl unmake_str($quote->{DATA}) . "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
#####################################################################
|
||||||
|
# parse a parsed IDL into a C header
|
||||||
|
sub Parse($)
|
||||||
|
{
|
||||||
|
my($ndr) = shift;
|
||||||
|
$tab_depth = 0;
|
||||||
|
|
||||||
|
$res = "";
|
||||||
|
%headerstructs = ();
|
||||||
|
pidl "/* header auto-generated by pidl */\n\n";
|
||||||
|
|
||||||
|
my $ifacename = "";
|
||||||
|
|
||||||
|
# work out a unique interface name
|
||||||
|
foreach (@{$ndr}) {
|
||||||
|
if ($_->{TYPE} eq "INTERFACE") {
|
||||||
|
$ifacename = $_->{NAME};
|
||||||
|
last;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pidl "#ifndef _PIDL_HEADER_$ifacename\n";
|
||||||
|
pidl "#define _PIDL_HEADER_$ifacename\n\n";
|
||||||
|
|
||||||
|
if (!is_intree()) {
|
||||||
|
pidl "#include <util/data_blob.h>\n";
|
||||||
|
}
|
||||||
|
pidl "#include <stdint.h>\n";
|
||||||
|
pidl "\n";
|
||||||
|
# FIXME: Include this only if NTSTATUS was actually used
|
||||||
|
pidl choose_header("libcli/util/ntstatus.h", "core/ntstatus.h") . "\n";
|
||||||
|
pidl "\n";
|
||||||
|
|
||||||
|
foreach (@{$ndr}) {
|
||||||
|
($_->{TYPE} eq "CPP_QUOTE") && HeaderQuote($_);
|
||||||
|
($_->{TYPE} eq "INTERFACE") && HeaderInterface($_);
|
||||||
|
($_->{TYPE} eq "IMPORT") && HeaderImport(@{$_->{PATHS}});
|
||||||
|
($_->{TYPE} eq "INCLUDE") && HeaderInclude(@{$_->{PATHS}});
|
||||||
|
}
|
||||||
|
|
||||||
|
pidl "#endif /* _PIDL_HEADER_$ifacename */\n";
|
||||||
|
|
||||||
|
return $res;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub GenerateStructEnv($$)
|
||||||
|
{
|
||||||
|
my ($x, $v) = @_;
|
||||||
|
my %env;
|
||||||
|
|
||||||
|
foreach my $e (@{$x->{ELEMENTS}}) {
|
||||||
|
$env{$e->{NAME}} = "$v->$e->{NAME}";
|
||||||
|
}
|
||||||
|
|
||||||
|
$env{"this"} = $v;
|
||||||
|
|
||||||
|
return \%env;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub EnvSubstituteValue($$)
|
||||||
|
{
|
||||||
|
my ($env,$s) = @_;
|
||||||
|
|
||||||
|
# Substitute the value() values in the env
|
||||||
|
foreach my $e (@{$s->{ELEMENTS}}) {
|
||||||
|
next unless (defined(my $v = has_property($e, "value")));
|
||||||
|
|
||||||
|
$env->{$e->{NAME}} = ParseExpr($v, $env, $e);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $env;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub GenerateFunctionInEnv($;$)
|
||||||
|
{
|
||||||
|
my ($fn, $base) = @_;
|
||||||
|
my %env;
|
||||||
|
|
||||||
|
$base = "r->" unless defined($base);
|
||||||
|
|
||||||
|
foreach my $e (@{$fn->{ELEMENTS}}) {
|
||||||
|
if (grep (/in/, @{$e->{DIRECTION}})) {
|
||||||
|
$env{$e->{NAME}} = $base."in.$e->{NAME}";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return \%env;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub GenerateFunctionOutEnv($;$)
|
||||||
|
{
|
||||||
|
my ($fn, $base) = @_;
|
||||||
|
my %env;
|
||||||
|
|
||||||
|
$base = "r->" unless defined($base);
|
||||||
|
|
||||||
|
foreach my $e (@{$fn->{ELEMENTS}}) {
|
||||||
|
if (grep (/out/, @{$e->{DIRECTION}})) {
|
||||||
|
$env{$e->{NAME}} = $base."out.$e->{NAME}";
|
||||||
|
} elsif (grep (/in/, @{$e->{DIRECTION}})) {
|
||||||
|
$env{$e->{NAME}} = $base."in.$e->{NAME}";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return \%env;
|
||||||
|
}
|
||||||
|
|
||||||
|
1;
|
875
tools/pidl/lib/Parse/Pidl/Samba4/NDR/Client.pm
Normal file
875
tools/pidl/lib/Parse/Pidl/Samba4/NDR/Client.pm
Normal file
|
@ -0,0 +1,875 @@
|
||||||
|
###################################################
|
||||||
|
# client calls generator
|
||||||
|
# Copyright tridge@samba.org 2003
|
||||||
|
# Copyright jelmer@samba.org 2005-2006
|
||||||
|
# released under the GNU GPL
|
||||||
|
|
||||||
|
package Parse::Pidl::Samba4::NDR::Client;
|
||||||
|
|
||||||
|
use Exporter;
|
||||||
|
@ISA = qw(Exporter);
|
||||||
|
@EXPORT_OK = qw(Parse);
|
||||||
|
|
||||||
|
use Parse::Pidl qw(fatal warning error);
|
||||||
|
use Parse::Pidl::Util qw(has_property ParseExpr);
|
||||||
|
use Parse::Pidl::NDR qw(ContainsPipe);
|
||||||
|
use Parse::Pidl::Typelist qw(mapTypeName);
|
||||||
|
use Parse::Pidl::Samba4 qw(choose_header is_intree DeclLong);
|
||||||
|
use Parse::Pidl::Samba4::Header qw(GenerateFunctionInEnv GenerateFunctionOutEnv);
|
||||||
|
|
||||||
|
use vars qw($VERSION);
|
||||||
|
$VERSION = '0.01';
|
||||||
|
|
||||||
|
use strict;
|
||||||
|
|
||||||
|
sub indent($) { my ($self) = @_; $self->{tabs}.="\t"; }
|
||||||
|
sub deindent($) { my ($self) = @_; $self->{tabs} = substr($self->{tabs}, 1); }
|
||||||
|
sub pidl($$) { my ($self,$txt) = @_; $self->{res} .= $txt ? "$self->{tabs}$txt\n" : "\n"; }
|
||||||
|
sub pidl_hdr($$) { my ($self, $txt) = @_; $self->{res_hdr} .= "$txt\n"; }
|
||||||
|
sub pidl_both($$) { my ($self, $txt) = @_; $self->{hdr} .= "$txt\n"; $self->{res_hdr} .= "$txt\n"; }
|
||||||
|
sub fn_declare($$) { my ($self,$n) = @_; $self->pidl($n); $self->pidl_hdr("$n;"); }
|
||||||
|
|
||||||
|
sub genpad($)
|
||||||
|
{
|
||||||
|
my ($s) = @_;
|
||||||
|
my $nt = int((length($s)+1)/8);
|
||||||
|
my $lt = ($nt*8)-1;
|
||||||
|
my $ns = (length($s)-$lt);
|
||||||
|
return "\t"x($nt)." "x($ns);
|
||||||
|
}
|
||||||
|
|
||||||
|
sub new($)
|
||||||
|
{
|
||||||
|
my ($class) = shift;
|
||||||
|
my $self = { res => "", res_hdr => "", tabs => "" };
|
||||||
|
bless($self, $class);
|
||||||
|
}
|
||||||
|
|
||||||
|
sub ParseFunctionHasPipes($$)
|
||||||
|
{
|
||||||
|
my ($self, $fn) = @_;
|
||||||
|
|
||||||
|
foreach my $e (@{$fn->{ELEMENTS}}) {
|
||||||
|
return 1 if ContainsPipe($e, $e->{LEVELS}[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub ParseFunction_r_State($$$$)
|
||||||
|
{
|
||||||
|
my ($self, $if, $fn, $name) = @_;
|
||||||
|
my $uname = uc $name;
|
||||||
|
|
||||||
|
$self->pidl("struct dcerpc_$name\_r_state {");
|
||||||
|
$self->indent;
|
||||||
|
$self->pidl("TALLOC_CTX *out_mem_ctx;");
|
||||||
|
$self->deindent;
|
||||||
|
$self->pidl("};");
|
||||||
|
$self->pidl("");
|
||||||
|
$self->pidl("static void dcerpc_$name\_r_done(struct tevent_req *subreq);");
|
||||||
|
$self->pidl("");
|
||||||
|
}
|
||||||
|
|
||||||
|
sub ParseFunction_r_Send($$$$)
|
||||||
|
{
|
||||||
|
my ($self, $if, $fn, $name) = @_;
|
||||||
|
my $uname = uc $name;
|
||||||
|
|
||||||
|
my $proto = "struct tevent_req *dcerpc_$name\_r_send(TALLOC_CTX *mem_ctx,\n";
|
||||||
|
$proto .= "\tstruct tevent_context *ev,\n",
|
||||||
|
$proto .= "\tstruct dcerpc_binding_handle *h,\n",
|
||||||
|
$proto .= "\tstruct $name *r)";
|
||||||
|
|
||||||
|
$self->fn_declare($proto);
|
||||||
|
|
||||||
|
$self->pidl("{");
|
||||||
|
$self->indent;
|
||||||
|
|
||||||
|
$self->pidl("struct tevent_req *req;");
|
||||||
|
$self->pidl("struct dcerpc_$name\_r_state *state;");
|
||||||
|
$self->pidl("struct tevent_req *subreq;");
|
||||||
|
$self->pidl("");
|
||||||
|
|
||||||
|
$self->pidl("req = tevent_req_create(mem_ctx, &state,");
|
||||||
|
$self->pidl("\t\t\tstruct dcerpc_$name\_r_state);");
|
||||||
|
$self->pidl("if (req == NULL) {");
|
||||||
|
$self->indent;
|
||||||
|
$self->pidl("return NULL;");
|
||||||
|
$self->deindent;
|
||||||
|
$self->pidl("}");
|
||||||
|
$self->pidl("");
|
||||||
|
|
||||||
|
my $out_params = 0;
|
||||||
|
foreach my $e (@{$fn->{ELEMENTS}}) {
|
||||||
|
next unless grep(/out/, @{$e->{DIRECTION}});
|
||||||
|
next if ContainsPipe($e, $e->{LEVELS}[0]);
|
||||||
|
$out_params++;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
my $submem;
|
||||||
|
if ($out_params > 0) {
|
||||||
|
$self->pidl("state->out_mem_ctx = talloc_new(state);");
|
||||||
|
$self->pidl("if (tevent_req_nomem(state->out_mem_ctx, req)) {");
|
||||||
|
$self->indent;
|
||||||
|
$self->pidl("return tevent_req_post(req, ev);");
|
||||||
|
$self->deindent;
|
||||||
|
$self->pidl("}");
|
||||||
|
$submem = "state->out_mem_ctx";
|
||||||
|
} else {
|
||||||
|
$self->pidl("state->out_mem_ctx = NULL;");
|
||||||
|
$submem = "state";
|
||||||
|
}
|
||||||
|
$self->pidl("");
|
||||||
|
|
||||||
|
$self->pidl("subreq = dcerpc_binding_handle_call_send(state, ev, h,");
|
||||||
|
$self->pidl("\t\tNULL, &ndr_table_$if->{NAME},");
|
||||||
|
$self->pidl("\t\tNDR_$uname, $submem, r);");
|
||||||
|
$self->pidl("if (tevent_req_nomem(subreq, req)) {");
|
||||||
|
$self->indent;
|
||||||
|
$self->pidl("return tevent_req_post(req, ev);");
|
||||||
|
$self->deindent;
|
||||||
|
$self->pidl("}");
|
||||||
|
$self->pidl("tevent_req_set_callback(subreq, dcerpc_$name\_r_done, req);");
|
||||||
|
$self->pidl("");
|
||||||
|
|
||||||
|
$self->pidl("return req;");
|
||||||
|
$self->deindent;
|
||||||
|
$self->pidl("}");
|
||||||
|
$self->pidl("");
|
||||||
|
}
|
||||||
|
|
||||||
|
sub ParseFunction_r_Done($$$$)
|
||||||
|
{
|
||||||
|
my ($self, $if, $fn, $name) = @_;
|
||||||
|
my $uname = uc $name;
|
||||||
|
|
||||||
|
my $proto = "static void dcerpc_$name\_r_done(struct tevent_req *subreq)";
|
||||||
|
|
||||||
|
$self->pidl("$proto");
|
||||||
|
$self->pidl("{");
|
||||||
|
$self->indent;
|
||||||
|
|
||||||
|
$self->pidl("struct tevent_req *req =");
|
||||||
|
$self->pidl("\ttevent_req_callback_data(subreq,");
|
||||||
|
$self->pidl("\tstruct tevent_req);");
|
||||||
|
$self->pidl("NTSTATUS status;");
|
||||||
|
$self->pidl("");
|
||||||
|
|
||||||
|
$self->pidl("status = dcerpc_binding_handle_call_recv(subreq);");
|
||||||
|
$self->pidl("if (!NT_STATUS_IS_OK(status)) {");
|
||||||
|
$self->indent;
|
||||||
|
$self->pidl("tevent_req_nterror(req, status);");
|
||||||
|
$self->pidl("return;");
|
||||||
|
$self->deindent;
|
||||||
|
$self->pidl("}");
|
||||||
|
$self->pidl("");
|
||||||
|
|
||||||
|
$self->pidl("tevent_req_done(req);");
|
||||||
|
$self->deindent;
|
||||||
|
$self->pidl("}");
|
||||||
|
$self->pidl("");
|
||||||
|
}
|
||||||
|
|
||||||
|
sub ParseFunction_r_Recv($$$$)
|
||||||
|
{
|
||||||
|
my ($self, $if, $fn, $name) = @_;
|
||||||
|
my $uname = uc $name;
|
||||||
|
|
||||||
|
my $proto = "NTSTATUS dcerpc_$name\_r_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx)";
|
||||||
|
|
||||||
|
$self->fn_declare($proto);
|
||||||
|
|
||||||
|
$self->pidl("{");
|
||||||
|
$self->indent;
|
||||||
|
|
||||||
|
$self->pidl("struct dcerpc_$name\_r_state *state =");
|
||||||
|
$self->pidl("\ttevent_req_data(req,");
|
||||||
|
$self->pidl("\tstruct dcerpc_$name\_r_state);");
|
||||||
|
$self->pidl("NTSTATUS status;");
|
||||||
|
$self->pidl("");
|
||||||
|
|
||||||
|
$self->pidl("if (tevent_req_is_nterror(req, &status)) {");
|
||||||
|
$self->indent;
|
||||||
|
$self->pidl("tevent_req_received(req);");
|
||||||
|
$self->pidl("return status;");
|
||||||
|
$self->deindent;
|
||||||
|
$self->pidl("}");
|
||||||
|
$self->pidl("");
|
||||||
|
|
||||||
|
$self->pidl("talloc_steal(mem_ctx, state->out_mem_ctx);");
|
||||||
|
$self->pidl("");
|
||||||
|
|
||||||
|
$self->pidl("tevent_req_received(req);");
|
||||||
|
$self->pidl("return NT_STATUS_OK;");
|
||||||
|
$self->deindent;
|
||||||
|
$self->pidl("}");
|
||||||
|
$self->pidl("");
|
||||||
|
}
|
||||||
|
|
||||||
|
sub ParseFunction_r_Sync($$$$)
|
||||||
|
{
|
||||||
|
my ($self, $if, $fn, $name) = @_;
|
||||||
|
my $uname = uc $name;
|
||||||
|
|
||||||
|
if ($self->ParseFunctionHasPipes($fn)) {
|
||||||
|
$self->pidl_both("/*");
|
||||||
|
$self->pidl_both(" * The following function is skipped because");
|
||||||
|
$self->pidl_both(" * it uses pipes:");
|
||||||
|
$self->pidl_both(" *");
|
||||||
|
$self->pidl_both(" * dcerpc_$name\_r()");
|
||||||
|
$self->pidl_both(" */");
|
||||||
|
$self->pidl_both("");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
my $proto = "NTSTATUS dcerpc_$name\_r(struct dcerpc_binding_handle *h, TALLOC_CTX *mem_ctx, struct $name *r)";
|
||||||
|
|
||||||
|
$self->fn_declare($proto);
|
||||||
|
|
||||||
|
$self->pidl("{");
|
||||||
|
$self->indent;
|
||||||
|
$self->pidl("NTSTATUS status;");
|
||||||
|
$self->pidl("");
|
||||||
|
|
||||||
|
$self->pidl("status = dcerpc_binding_handle_call(h,");
|
||||||
|
$self->pidl("\t\tNULL, &ndr_table_$if->{NAME},");
|
||||||
|
$self->pidl("\t\tNDR_$uname, mem_ctx, r);");
|
||||||
|
$self->pidl("");
|
||||||
|
$self->pidl("return status;");
|
||||||
|
|
||||||
|
$self->deindent;
|
||||||
|
$self->pidl("}");
|
||||||
|
$self->pidl("");
|
||||||
|
}
|
||||||
|
|
||||||
|
sub ElementDirection($)
|
||||||
|
{
|
||||||
|
my ($e) = @_;
|
||||||
|
|
||||||
|
return "[in,out]" if (has_property($e, "in") and has_property($e, "out"));
|
||||||
|
return "[in]" if (has_property($e, "in"));
|
||||||
|
return "[out]" if (has_property($e, "out"));
|
||||||
|
return "[in,out]";
|
||||||
|
}
|
||||||
|
|
||||||
|
sub HeaderProperties($$)
|
||||||
|
{
|
||||||
|
my($props,$ignores) = @_;
|
||||||
|
my $ret = "";
|
||||||
|
|
||||||
|
foreach my $d (keys %{$props}) {
|
||||||
|
next if (grep(/^$d$/, @$ignores));
|
||||||
|
if($props->{$d} ne "1") {
|
||||||
|
$ret.= "$d($props->{$d}),";
|
||||||
|
} else {
|
||||||
|
$ret.="$d,";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($ret) {
|
||||||
|
return "[" . substr($ret, 0, -1) . "]";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sub ParseCopyArgument($$$$$)
|
||||||
|
{
|
||||||
|
my ($self, $fn, $e, $r, $i) = @_;
|
||||||
|
my $l = $e->{LEVELS}[0];
|
||||||
|
|
||||||
|
if ($l->{TYPE} eq "ARRAY" and $l->{IS_FIXED} == 1) {
|
||||||
|
$self->pidl("memcpy(${r}$e->{NAME}, ${i}$e->{NAME}, sizeof(${r}$e->{NAME}));");
|
||||||
|
} else {
|
||||||
|
$self->pidl("${r}$e->{NAME} = ${i}$e->{NAME};");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sub ParseInvalidResponse($$)
|
||||||
|
{
|
||||||
|
my ($self, $type) = @_;
|
||||||
|
|
||||||
|
if ($type eq "sync") {
|
||||||
|
$self->pidl("return NT_STATUS_INVALID_NETWORK_RESPONSE;");
|
||||||
|
} elsif ($type eq "async") {
|
||||||
|
$self->pidl("tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);");
|
||||||
|
$self->pidl("return;");
|
||||||
|
} else {
|
||||||
|
die("ParseInvalidResponse($type)");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sub ParseOutputArgument($$$$$$)
|
||||||
|
{
|
||||||
|
my ($self, $fn, $e, $r, $o, $invalid_response_type) = @_;
|
||||||
|
my $level = 0;
|
||||||
|
|
||||||
|
if ($e->{LEVELS}[0]->{TYPE} ne "POINTER" and $e->{LEVELS}[0]->{TYPE} ne "ARRAY") {
|
||||||
|
fatal($e->{ORIGINAL}, "[out] argument is not a pointer or array");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($e->{LEVELS}[0]->{TYPE} eq "POINTER") {
|
||||||
|
$level = 1;
|
||||||
|
if ($e->{LEVELS}[0]->{POINTER_TYPE} ne "ref") {
|
||||||
|
$self->pidl("if ($o$e->{NAME} && ${r}out.$e->{NAME}) {");
|
||||||
|
$self->indent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($e->{LEVELS}[$level]->{TYPE} eq "ARRAY") {
|
||||||
|
# This is a call to GenerateFunctionInEnv intentionally.
|
||||||
|
# Since the data is being copied into a user-provided data
|
||||||
|
# structure, the user should be able to know the size beforehand
|
||||||
|
# to allocate a structure of the right size.
|
||||||
|
my $in_env = GenerateFunctionInEnv($fn, $r);
|
||||||
|
my $out_env = GenerateFunctionOutEnv($fn, $r);
|
||||||
|
my $l = $e->{LEVELS}[$level];
|
||||||
|
|
||||||
|
my $in_var = undef;
|
||||||
|
if (grep(/in/, @{$e->{DIRECTION}})) {
|
||||||
|
$in_var = ParseExpr($e->{NAME}, $in_env, $e->{ORIGINAL});
|
||||||
|
}
|
||||||
|
my $out_var = ParseExpr($e->{NAME}, $out_env, $e->{ORIGINAL});
|
||||||
|
|
||||||
|
my $in_size_is = undef;
|
||||||
|
my $out_size_is = undef;
|
||||||
|
my $out_length_is = undef;
|
||||||
|
|
||||||
|
my $avail_len = undef;
|
||||||
|
my $needed_len = undef;
|
||||||
|
|
||||||
|
$self->pidl("{");
|
||||||
|
$self->indent;
|
||||||
|
my $copy_len_var = "_copy_len_$e->{NAME}";
|
||||||
|
$self->pidl("size_t $copy_len_var;");
|
||||||
|
|
||||||
|
if (not defined($l->{SIZE_IS})) {
|
||||||
|
if (not $l->{IS_ZERO_TERMINATED}) {
|
||||||
|
fatal($e->{ORIGINAL}, "no size known for [out] array `$e->{NAME}'");
|
||||||
|
}
|
||||||
|
if (has_property($e, "charset")) {
|
||||||
|
$avail_len = "ndr_charset_length($in_var, CH_UNIX)";
|
||||||
|
$needed_len = "ndr_charset_length($out_var, CH_UNIX)";
|
||||||
|
} else {
|
||||||
|
$avail_len = "ndr_string_length($in_var, sizeof(*$in_var))";
|
||||||
|
$needed_len = "ndr_string_length($out_var, sizeof(*$out_var))";
|
||||||
|
}
|
||||||
|
$in_size_is = "";
|
||||||
|
$out_size_is = "";
|
||||||
|
$out_length_is = "";
|
||||||
|
} else {
|
||||||
|
$in_size_is = ParseExpr($l->{SIZE_IS}, $in_env, $e->{ORIGINAL});
|
||||||
|
$out_size_is = ParseExpr($l->{SIZE_IS}, $out_env, $e->{ORIGINAL});
|
||||||
|
$out_length_is = $out_size_is;
|
||||||
|
if (defined($l->{LENGTH_IS})) {
|
||||||
|
$out_length_is = ParseExpr($l->{LENGTH_IS}, $out_env, $e->{ORIGINAL});
|
||||||
|
}
|
||||||
|
if (has_property($e, "charset")) {
|
||||||
|
if (defined($in_var)) {
|
||||||
|
$avail_len = "ndr_charset_length($in_var, CH_UNIX)";
|
||||||
|
} else {
|
||||||
|
$avail_len = $out_length_is;
|
||||||
|
}
|
||||||
|
$needed_len = "ndr_charset_length($out_var, CH_UNIX)";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($out_size_is ne $in_size_is) {
|
||||||
|
$self->pidl("if (($out_size_is) > ($in_size_is)) {");
|
||||||
|
$self->indent;
|
||||||
|
$self->ParseInvalidResponse($invalid_response_type);
|
||||||
|
$self->deindent;
|
||||||
|
$self->pidl("}");
|
||||||
|
}
|
||||||
|
if ($out_length_is ne $out_size_is) {
|
||||||
|
$self->pidl("if (($out_length_is) > ($out_size_is)) {");
|
||||||
|
$self->indent;
|
||||||
|
$self->ParseInvalidResponse($invalid_response_type);
|
||||||
|
$self->deindent;
|
||||||
|
$self->pidl("}");
|
||||||
|
}
|
||||||
|
if (defined($needed_len)) {
|
||||||
|
$self->pidl("$copy_len_var = $needed_len;");
|
||||||
|
$self->pidl("if ($copy_len_var > $avail_len) {");
|
||||||
|
$self->indent;
|
||||||
|
$self->ParseInvalidResponse($invalid_response_type);
|
||||||
|
$self->deindent;
|
||||||
|
$self->pidl("}");
|
||||||
|
} else {
|
||||||
|
$self->pidl("$copy_len_var = $out_length_is;");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (has_property($e, "charset")) {
|
||||||
|
$self->pidl("memcpy(discard_const_p(uint8_t *, $o$e->{NAME}), $out_var, $copy_len_var * sizeof(*$o$e->{NAME}));");
|
||||||
|
} else {
|
||||||
|
$self->pidl("memcpy($o$e->{NAME}, $out_var, $copy_len_var * sizeof(*$o$e->{NAME}));");
|
||||||
|
}
|
||||||
|
|
||||||
|
$self->deindent;
|
||||||
|
$self->pidl("}");
|
||||||
|
} else {
|
||||||
|
$self->pidl("*$o$e->{NAME} = *${r}out.$e->{NAME};");
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($e->{LEVELS}[0]->{TYPE} eq "POINTER") {
|
||||||
|
if ($e->{LEVELS}[0]->{POINTER_TYPE} ne "ref") {
|
||||||
|
$self->deindent;
|
||||||
|
$self->pidl("}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sub ParseFunction_State($$$$)
|
||||||
|
{
|
||||||
|
my ($self, $if, $fn, $name) = @_;
|
||||||
|
|
||||||
|
my $state_str = "struct dcerpc_$name\_state";
|
||||||
|
my $done_fn = "dcerpc_$name\_done";
|
||||||
|
|
||||||
|
$self->pidl("$state_str {");
|
||||||
|
$self->indent;
|
||||||
|
$self->pidl("struct $name orig;");
|
||||||
|
$self->pidl("struct $name tmp;");
|
||||||
|
$self->pidl("TALLOC_CTX *out_mem_ctx;");
|
||||||
|
$self->deindent;
|
||||||
|
$self->pidl("};");
|
||||||
|
$self->pidl("");
|
||||||
|
$self->pidl("static void $done_fn(struct tevent_req *subreq);");
|
||||||
|
$self->pidl("");
|
||||||
|
}
|
||||||
|
|
||||||
|
sub ParseFunction_Send($$$$)
|
||||||
|
{
|
||||||
|
my ($self, $if, $fn, $name) = @_;
|
||||||
|
|
||||||
|
my $fn_args = "";
|
||||||
|
my $state_str = "struct dcerpc_$name\_state";
|
||||||
|
my $done_fn = "dcerpc_$name\_done";
|
||||||
|
my $out_mem_ctx = "dcerpc_$name\_out_memory";
|
||||||
|
my $fn_str = "struct tevent_req *dcerpc_$name\_send";
|
||||||
|
my $pad = genpad($fn_str);
|
||||||
|
|
||||||
|
$fn_args .= "TALLOC_CTX *mem_ctx";
|
||||||
|
$fn_args .= ",\n" . $pad . "struct tevent_context *ev";
|
||||||
|
$fn_args .= ",\n" . $pad . "struct dcerpc_binding_handle *h";
|
||||||
|
|
||||||
|
foreach (@{$fn->{ELEMENTS}}) {
|
||||||
|
my $dir = ElementDirection($_);
|
||||||
|
my $prop = HeaderProperties($_->{PROPERTIES}, ["in", "out"]);
|
||||||
|
$fn_args .= ",\n" . $pad . DeclLong($_, "_") . " /* $dir $prop */";
|
||||||
|
}
|
||||||
|
|
||||||
|
$self->fn_declare("$fn_str($fn_args)");
|
||||||
|
$self->pidl("{");
|
||||||
|
$self->indent;
|
||||||
|
$self->pidl("struct tevent_req *req;");
|
||||||
|
$self->pidl("$state_str *state;");
|
||||||
|
$self->pidl("struct tevent_req *subreq;");
|
||||||
|
$self->pidl("");
|
||||||
|
$self->pidl("req = tevent_req_create(mem_ctx, &state,");
|
||||||
|
$self->pidl("\t\t\t$state_str);");
|
||||||
|
$self->pidl("if (req == NULL) {");
|
||||||
|
$self->indent;
|
||||||
|
$self->pidl("return NULL;");
|
||||||
|
$self->deindent;
|
||||||
|
$self->pidl("}");
|
||||||
|
$self->pidl("state->out_mem_ctx = NULL;");
|
||||||
|
$self->pidl("");
|
||||||
|
|
||||||
|
$self->pidl("/* In parameters */");
|
||||||
|
foreach my $e (@{$fn->{ELEMENTS}}) {
|
||||||
|
next unless (grep(/in/, @{$e->{DIRECTION}}));
|
||||||
|
|
||||||
|
$self->ParseCopyArgument($fn, $e, "state->orig.in.", "_");
|
||||||
|
}
|
||||||
|
$self->pidl("");
|
||||||
|
|
||||||
|
my $out_params = 0;
|
||||||
|
$self->pidl("/* Out parameters */");
|
||||||
|
foreach my $e (@{$fn->{ELEMENTS}}) {
|
||||||
|
next unless grep(/out/, @{$e->{DIRECTION}});
|
||||||
|
|
||||||
|
$self->ParseCopyArgument($fn, $e, "state->orig.out.", "_");
|
||||||
|
|
||||||
|
next if ContainsPipe($e, $e->{LEVELS}[0]);
|
||||||
|
|
||||||
|
$out_params++;
|
||||||
|
}
|
||||||
|
$self->pidl("");
|
||||||
|
|
||||||
|
if (defined($fn->{RETURN_TYPE})) {
|
||||||
|
$self->pidl("/* Result */");
|
||||||
|
$self->pidl("ZERO_STRUCT(state->orig.out.result);");
|
||||||
|
$self->pidl("");
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($out_params > 0) {
|
||||||
|
$self->pidl("state->out_mem_ctx = talloc_named_const(state, 0,");
|
||||||
|
$self->pidl("\t\t \"$out_mem_ctx\");");
|
||||||
|
$self->pidl("if (tevent_req_nomem(state->out_mem_ctx, req)) {");
|
||||||
|
$self->indent;
|
||||||
|
$self->pidl("return tevent_req_post(req, ev);");
|
||||||
|
$self->deindent;
|
||||||
|
$self->pidl("}");
|
||||||
|
$self->pidl("");
|
||||||
|
}
|
||||||
|
|
||||||
|
$self->pidl("/* make a temporary copy, that we pass to the dispatch function */");
|
||||||
|
$self->pidl("state->tmp = state->orig;");
|
||||||
|
$self->pidl("");
|
||||||
|
|
||||||
|
$self->pidl("subreq = dcerpc_$name\_r_send(state, ev, h, &state->tmp);");
|
||||||
|
$self->pidl("if (tevent_req_nomem(subreq, req)) {");
|
||||||
|
$self->indent;
|
||||||
|
$self->pidl("return tevent_req_post(req, ev);");
|
||||||
|
$self->deindent;
|
||||||
|
$self->pidl("}");
|
||||||
|
$self->pidl("tevent_req_set_callback(subreq, $done_fn, req);");
|
||||||
|
$self->pidl("return req;");
|
||||||
|
$self->deindent;
|
||||||
|
$self->pidl("}");
|
||||||
|
$self->pidl("");
|
||||||
|
}
|
||||||
|
|
||||||
|
sub ParseFunction_Done($$$$)
|
||||||
|
{
|
||||||
|
my ($self, $if, $fn, $name) = @_;
|
||||||
|
|
||||||
|
my $state_str = "struct dcerpc_$name\_state";
|
||||||
|
my $done_fn = "dcerpc_$name\_done";
|
||||||
|
|
||||||
|
$self->pidl("static void $done_fn(struct tevent_req *subreq)");
|
||||||
|
$self->pidl("{");
|
||||||
|
$self->indent;
|
||||||
|
$self->pidl("struct tevent_req *req = tevent_req_callback_data(");
|
||||||
|
$self->pidl("\tsubreq, struct tevent_req);");
|
||||||
|
$self->pidl("$state_str *state = tevent_req_data(");
|
||||||
|
$self->pidl("\treq, $state_str);");
|
||||||
|
$self->pidl("NTSTATUS status;");
|
||||||
|
$self->pidl("TALLOC_CTX *mem_ctx;");
|
||||||
|
$self->pidl("");
|
||||||
|
|
||||||
|
$self->pidl("if (state->out_mem_ctx) {");
|
||||||
|
$self->indent;
|
||||||
|
$self->pidl("mem_ctx = state->out_mem_ctx;");
|
||||||
|
$self->deindent;
|
||||||
|
$self->pidl("} else {");
|
||||||
|
$self->indent;
|
||||||
|
$self->pidl("mem_ctx = state;");
|
||||||
|
$self->deindent;
|
||||||
|
$self->pidl("}");
|
||||||
|
$self->pidl("");
|
||||||
|
|
||||||
|
$self->pidl("status = dcerpc_$name\_r_recv(subreq, mem_ctx);");
|
||||||
|
$self->pidl("TALLOC_FREE(subreq);");
|
||||||
|
$self->pidl("if (!NT_STATUS_IS_OK(status)) {");
|
||||||
|
$self->indent;
|
||||||
|
$self->pidl("tevent_req_nterror(req, status);");
|
||||||
|
$self->pidl("return;");
|
||||||
|
$self->deindent;
|
||||||
|
$self->pidl("}");
|
||||||
|
$self->pidl("");
|
||||||
|
|
||||||
|
$self->pidl("/* Copy out parameters */");
|
||||||
|
foreach my $e (@{$fn->{ELEMENTS}}) {
|
||||||
|
next if ContainsPipe($e, $e->{LEVELS}[0]);
|
||||||
|
next unless (grep(/out/, @{$e->{DIRECTION}}));
|
||||||
|
|
||||||
|
$self->ParseOutputArgument($fn, $e,
|
||||||
|
"state->tmp.",
|
||||||
|
"state->orig.out.",
|
||||||
|
"async");
|
||||||
|
}
|
||||||
|
$self->pidl("");
|
||||||
|
|
||||||
|
if (defined($fn->{RETURN_TYPE})) {
|
||||||
|
$self->pidl("/* Copy result */");
|
||||||
|
$self->pidl("state->orig.out.result = state->tmp.out.result;");
|
||||||
|
$self->pidl("");
|
||||||
|
}
|
||||||
|
|
||||||
|
$self->pidl("/* Reset temporary structure */");
|
||||||
|
$self->pidl("ZERO_STRUCT(state->tmp);");
|
||||||
|
$self->pidl("");
|
||||||
|
|
||||||
|
$self->pidl("tevent_req_done(req);");
|
||||||
|
$self->deindent;
|
||||||
|
$self->pidl("}");
|
||||||
|
$self->pidl("");
|
||||||
|
}
|
||||||
|
|
||||||
|
sub ParseFunction_Recv($$$$)
|
||||||
|
{
|
||||||
|
my ($self, $if, $fn, $name) = @_;
|
||||||
|
|
||||||
|
my $fn_args = "";
|
||||||
|
my $state_str = "struct dcerpc_$name\_state";
|
||||||
|
my $fn_str = "NTSTATUS dcerpc_$name\_recv";
|
||||||
|
my $pad = genpad($fn_str);
|
||||||
|
|
||||||
|
$fn_args .= "struct tevent_req *req,\n" . $pad . "TALLOC_CTX *mem_ctx";
|
||||||
|
|
||||||
|
if (defined($fn->{RETURN_TYPE})) {
|
||||||
|
$fn_args .= ",\n" . $pad . mapTypeName($fn->{RETURN_TYPE}). " *result";
|
||||||
|
}
|
||||||
|
|
||||||
|
$self->fn_declare("$fn_str($fn_args)");
|
||||||
|
$self->pidl("{");
|
||||||
|
$self->indent;
|
||||||
|
$self->pidl("$state_str *state = tevent_req_data(");
|
||||||
|
$self->pidl("\treq, $state_str);");
|
||||||
|
$self->pidl("NTSTATUS status;");
|
||||||
|
$self->pidl("");
|
||||||
|
$self->pidl("if (tevent_req_is_nterror(req, &status)) {");
|
||||||
|
$self->indent;
|
||||||
|
$self->pidl("tevent_req_received(req);");
|
||||||
|
$self->pidl("return status;");
|
||||||
|
$self->deindent;
|
||||||
|
$self->pidl("}");
|
||||||
|
$self->pidl("");
|
||||||
|
|
||||||
|
$self->pidl("/* Steal possible out parameters to the callers context */");
|
||||||
|
$self->pidl("talloc_steal(mem_ctx, state->out_mem_ctx);");
|
||||||
|
$self->pidl("");
|
||||||
|
|
||||||
|
if (defined($fn->{RETURN_TYPE})) {
|
||||||
|
$self->pidl("/* Return result */");
|
||||||
|
$self->pidl("*result = state->orig.out.result;");
|
||||||
|
$self->pidl("");
|
||||||
|
}
|
||||||
|
|
||||||
|
$self->pidl("tevent_req_received(req);");
|
||||||
|
$self->pidl("return NT_STATUS_OK;");
|
||||||
|
$self->deindent;
|
||||||
|
$self->pidl("}");
|
||||||
|
$self->pidl("");
|
||||||
|
}
|
||||||
|
|
||||||
|
sub ParseFunction_Sync($$$$)
|
||||||
|
{
|
||||||
|
my ($self, $if, $fn, $name) = @_;
|
||||||
|
|
||||||
|
if ($self->ParseFunctionHasPipes($fn)) {
|
||||||
|
$self->pidl_both("/*");
|
||||||
|
$self->pidl_both(" * The following function is skipped because");
|
||||||
|
$self->pidl_both(" * it uses pipes:");
|
||||||
|
$self->pidl_both(" *");
|
||||||
|
$self->pidl_both(" * dcerpc_$name()");
|
||||||
|
$self->pidl_both(" */");
|
||||||
|
$self->pidl_both("");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
my $uname = uc $name;
|
||||||
|
my $fn_args = "";
|
||||||
|
my $fn_str = "NTSTATUS dcerpc_$name";
|
||||||
|
my $pad = genpad($fn_str);
|
||||||
|
|
||||||
|
$fn_args .= "struct dcerpc_binding_handle *h,\n" . $pad . "TALLOC_CTX *mem_ctx";
|
||||||
|
|
||||||
|
foreach (@{$fn->{ELEMENTS}}) {
|
||||||
|
my $dir = ElementDirection($_);
|
||||||
|
my $prop = HeaderProperties($_->{PROPERTIES}, ["in", "out"]);
|
||||||
|
$fn_args .= ",\n" . $pad . DeclLong($_, "_") . " /* $dir $prop */";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (defined($fn->{RETURN_TYPE})) {
|
||||||
|
$fn_args .= ",\n" . $pad . mapTypeName($fn->{RETURN_TYPE}). " *result";
|
||||||
|
}
|
||||||
|
|
||||||
|
$self->fn_declare("$fn_str($fn_args)");
|
||||||
|
$self->pidl("{");
|
||||||
|
$self->indent;
|
||||||
|
$self->pidl("struct $name r;");
|
||||||
|
$self->pidl("NTSTATUS status;");
|
||||||
|
$self->pidl("");
|
||||||
|
|
||||||
|
$self->pidl("/* In parameters */");
|
||||||
|
foreach my $e (@{$fn->{ELEMENTS}}) {
|
||||||
|
next unless (grep(/in/, @{$e->{DIRECTION}}));
|
||||||
|
|
||||||
|
$self->ParseCopyArgument($fn, $e, "r.in.", "_");
|
||||||
|
}
|
||||||
|
$self->pidl("");
|
||||||
|
|
||||||
|
$self->pidl("status = dcerpc_$name\_r(h, mem_ctx, &r);");
|
||||||
|
$self->pidl("if (!NT_STATUS_IS_OK(status)) {");
|
||||||
|
$self->indent;
|
||||||
|
$self->pidl("return status;");
|
||||||
|
$self->deindent;
|
||||||
|
$self->pidl("}");
|
||||||
|
$self->pidl("");
|
||||||
|
|
||||||
|
$self->pidl("/* Return variables */");
|
||||||
|
foreach my $e (@{$fn->{ELEMENTS}}) {
|
||||||
|
next if ContainsPipe($e, $e->{LEVELS}[0]);
|
||||||
|
next unless (grep(/out/, @{$e->{DIRECTION}}));
|
||||||
|
|
||||||
|
$self->ParseOutputArgument($fn, $e, "r.", "_", "sync");
|
||||||
|
}
|
||||||
|
$self->pidl("");
|
||||||
|
|
||||||
|
$self->pidl("/* Return result */");
|
||||||
|
if ($fn->{RETURN_TYPE}) {
|
||||||
|
$self->pidl("*result = r.out.result;");
|
||||||
|
}
|
||||||
|
$self->pidl("");
|
||||||
|
|
||||||
|
$self->pidl("return NT_STATUS_OK;");
|
||||||
|
|
||||||
|
$self->deindent;
|
||||||
|
$self->pidl("}");
|
||||||
|
$self->pidl("");
|
||||||
|
}
|
||||||
|
|
||||||
|
#####################################################################
|
||||||
|
# parse a function
|
||||||
|
sub ParseFunction($$$)
|
||||||
|
{
|
||||||
|
my ($self, $if, $fn) = @_;
|
||||||
|
|
||||||
|
if ($self->ParseFunctionHasPipes($fn)) {
|
||||||
|
$self->pidl_both("/*");
|
||||||
|
$self->pidl_both(" * The following function is skipped because");
|
||||||
|
$self->pidl_both(" * it uses pipes:");
|
||||||
|
$self->pidl_both(" *");
|
||||||
|
$self->pidl_both(" * dcerpc_$fn->{NAME}_r_send()");
|
||||||
|
$self->pidl_both(" * dcerpc_$fn->{NAME}_r_recv()");
|
||||||
|
$self->pidl_both(" * dcerpc_$fn->{NAME}_r()");
|
||||||
|
$self->pidl_both(" *");
|
||||||
|
$self->pidl_both(" * dcerpc_$fn->{NAME}_send()");
|
||||||
|
$self->pidl_both(" * dcerpc_$fn->{NAME}_recv()");
|
||||||
|
$self->pidl_both(" * dcerpc_$fn->{NAME}()");
|
||||||
|
$self->pidl_both(" */");
|
||||||
|
$self->pidl_both("");
|
||||||
|
warning($fn->{ORIGINAL}, "$fn->{NAME}: dcerpc client does not support pipe yet");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$self->ParseFunction_r_State($if, $fn, $fn->{NAME});
|
||||||
|
$self->ParseFunction_r_Send($if, $fn, $fn->{NAME});
|
||||||
|
$self->ParseFunction_r_Done($if, $fn, $fn->{NAME});
|
||||||
|
$self->ParseFunction_r_Recv($if, $fn, $fn->{NAME});
|
||||||
|
$self->ParseFunction_r_Sync($if, $fn, $fn->{NAME});
|
||||||
|
|
||||||
|
foreach my $e (@{$fn->{ELEMENTS}}) {
|
||||||
|
next unless (grep(/out/, @{$e->{DIRECTION}}));
|
||||||
|
|
||||||
|
my $reason = "is not a pointer or array";
|
||||||
|
|
||||||
|
# TODO: make this fatal at NDR level
|
||||||
|
if ($e->{LEVELS}[0]->{TYPE} eq "POINTER") {
|
||||||
|
if ($e->{LEVELS}[1]->{TYPE} eq "DATA" and
|
||||||
|
$e->{LEVELS}[1]->{DATA_TYPE} eq "string") {
|
||||||
|
$reason = "is a pointer to type 'string'";
|
||||||
|
} elsif ($e->{LEVELS}[1]->{TYPE} eq "ARRAY" and
|
||||||
|
$e->{LEVELS}[1]->{IS_ZERO_TERMINATED}) {
|
||||||
|
next;
|
||||||
|
} elsif ($e->{LEVELS}[1]->{TYPE} eq "ARRAY" and
|
||||||
|
not defined($e->{LEVELS}[1]->{SIZE_IS})) {
|
||||||
|
$reason = "is a pointer to an unsized array";
|
||||||
|
} else {
|
||||||
|
next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ($e->{LEVELS}[0]->{TYPE} eq "ARRAY") {
|
||||||
|
if (not defined($e->{LEVELS}[0]->{SIZE_IS})) {
|
||||||
|
$reason = "is an unsized array";
|
||||||
|
} else {
|
||||||
|
next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$self->pidl_both("/*");
|
||||||
|
$self->pidl_both(" * The following functions are skipped because");
|
||||||
|
$self->pidl_both(" * an [out] argument $e->{NAME} $reason:");
|
||||||
|
$self->pidl_both(" *");
|
||||||
|
$self->pidl_both(" * dcerpc_$fn->{NAME}_send()");
|
||||||
|
$self->pidl_both(" * dcerpc_$fn->{NAME}_recv()");
|
||||||
|
$self->pidl_both(" * dcerpc_$fn->{NAME}()");
|
||||||
|
$self->pidl_both(" */");
|
||||||
|
$self->pidl_both("");
|
||||||
|
|
||||||
|
error($e->{ORIGINAL}, "$fn->{NAME}: [out] argument '$e->{NAME}' $reason, skip client functions");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$self->ParseFunction_State($if, $fn, $fn->{NAME});
|
||||||
|
$self->ParseFunction_Send($if, $fn, $fn->{NAME});
|
||||||
|
$self->ParseFunction_Done($if, $fn, $fn->{NAME});
|
||||||
|
$self->ParseFunction_Recv($if, $fn, $fn->{NAME});
|
||||||
|
$self->ParseFunction_Sync($if, $fn, $fn->{NAME});
|
||||||
|
|
||||||
|
$self->pidl_hdr("");
|
||||||
|
}
|
||||||
|
|
||||||
|
my %done;
|
||||||
|
|
||||||
|
#####################################################################
|
||||||
|
# parse the interface definitions
|
||||||
|
sub ParseInterface($$)
|
||||||
|
{
|
||||||
|
my ($self, $if) = @_;
|
||||||
|
my $ifu = uc($if->{NAME});
|
||||||
|
|
||||||
|
$self->pidl_hdr("#ifndef _HEADER_RPC_$if->{NAME}");
|
||||||
|
$self->pidl_hdr("#define _HEADER_RPC_$if->{NAME}");
|
||||||
|
$self->pidl_hdr("");
|
||||||
|
|
||||||
|
if (defined $if->{PROPERTIES}->{uuid}) {
|
||||||
|
$self->pidl_hdr("extern const struct ndr_interface_table ndr_table_$if->{NAME};");
|
||||||
|
$self->pidl_hdr("");
|
||||||
|
}
|
||||||
|
|
||||||
|
$self->pidl("/* $if->{NAME} - client functions generated by pidl */");
|
||||||
|
$self->pidl("");
|
||||||
|
|
||||||
|
foreach my $fn (@{$if->{FUNCTIONS}}) {
|
||||||
|
next if defined($done{$fn->{NAME}});
|
||||||
|
next if has_property($fn, "noopnum");
|
||||||
|
next if has_property($fn, "todo");
|
||||||
|
$self->ParseFunction($if, $fn);
|
||||||
|
$done{$fn->{NAME}} = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
$self->pidl_hdr("#endif /* _HEADER_RPC_$if->{NAME} */");
|
||||||
|
}
|
||||||
|
|
||||||
|
sub Parse($$$$$$)
|
||||||
|
{
|
||||||
|
my($self,$ndr,$header,$ndr_header,$client_header) = @_;
|
||||||
|
|
||||||
|
$self->pidl("/* client functions auto-generated by pidl */");
|
||||||
|
$self->pidl("");
|
||||||
|
if (is_intree()) {
|
||||||
|
$self->pidl("#include \"includes.h\"");
|
||||||
|
} else {
|
||||||
|
$self->pidl("#ifndef _GNU_SOURCE");
|
||||||
|
$self->pidl("#define _GNU_SOURCE");
|
||||||
|
$self->pidl("#endif");
|
||||||
|
$self->pidl("#include <stdio.h>");
|
||||||
|
$self->pidl("#include <stdbool.h>");
|
||||||
|
$self->pidl("#include <stdlib.h>");
|
||||||
|
$self->pidl("#include <stdint.h>");
|
||||||
|
$self->pidl("#include <stdarg.h>");
|
||||||
|
$self->pidl("#include <string.h>");
|
||||||
|
$self->pidl("#include <core/ntstatus.h>");
|
||||||
|
}
|
||||||
|
$self->pidl("#include <tevent.h>");
|
||||||
|
$self->pidl(choose_header("lib/util/tevent_ntstatus.h", "util/tevent_ntstatus.h")."");
|
||||||
|
$self->pidl("#include \"$ndr_header\"");
|
||||||
|
$self->pidl("#include \"$client_header\"");
|
||||||
|
$self->pidl("");
|
||||||
|
|
||||||
|
$self->pidl_hdr(choose_header("librpc/rpc/dcerpc.h", "dcerpc.h")."");
|
||||||
|
$self->pidl_hdr("#include \"$header\"");
|
||||||
|
|
||||||
|
foreach my $x (@{$ndr}) {
|
||||||
|
($x->{TYPE} eq "INTERFACE") && $self->ParseInterface($x);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ($self->{res},$self->{res_hdr});
|
||||||
|
}
|
||||||
|
|
||||||
|
1;
|
3127
tools/pidl/lib/Parse/Pidl/Samba4/NDR/Parser.pm
Normal file
3127
tools/pidl/lib/Parse/Pidl/Samba4/NDR/Parser.pm
Normal file
File diff suppressed because it is too large
Load Diff
334
tools/pidl/lib/Parse/Pidl/Samba4/NDR/Server.pm
Normal file
334
tools/pidl/lib/Parse/Pidl/Samba4/NDR/Server.pm
Normal file
|
@ -0,0 +1,334 @@
|
||||||
|
###################################################
|
||||||
|
# server boilerplate generator
|
||||||
|
# Copyright tridge@samba.org 2003
|
||||||
|
# Copyright metze@samba.org 2004
|
||||||
|
# released under the GNU GPL
|
||||||
|
|
||||||
|
package Parse::Pidl::Samba4::NDR::Server;
|
||||||
|
|
||||||
|
use strict;
|
||||||
|
use Parse::Pidl::Util;
|
||||||
|
|
||||||
|
use vars qw($VERSION);
|
||||||
|
$VERSION = '0.01';
|
||||||
|
|
||||||
|
my($res);
|
||||||
|
|
||||||
|
sub pidl($)
|
||||||
|
{
|
||||||
|
$res .= shift;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#####################################################
|
||||||
|
# generate the switch statement for function dispatch
|
||||||
|
sub gen_dispatch_switch($)
|
||||||
|
{
|
||||||
|
my $interface = shift;
|
||||||
|
|
||||||
|
foreach my $fn (@{$interface->{FUNCTIONS}}) {
|
||||||
|
next if not defined($fn->{OPNUM});
|
||||||
|
|
||||||
|
pidl "\tcase $fn->{OPNUM}: {\n";
|
||||||
|
pidl "\t\tstruct $fn->{NAME} *r2 = (struct $fn->{NAME} *)r;\n";
|
||||||
|
pidl "\t\tif (DEBUGLEVEL >= 10) {\n";
|
||||||
|
pidl "\t\t\tNDR_PRINT_FUNCTION_DEBUG($fn->{NAME}, NDR_IN, r2);\n";
|
||||||
|
pidl "\t\t}\n";
|
||||||
|
if ($fn->{RETURN_TYPE} && $fn->{RETURN_TYPE} ne "void") {
|
||||||
|
pidl "\t\tr2->out.result = dcesrv_$fn->{NAME}(dce_call, mem_ctx, r2);\n";
|
||||||
|
} else {
|
||||||
|
pidl "\t\tdcesrv_$fn->{NAME}(dce_call, mem_ctx, r2);\n";
|
||||||
|
}
|
||||||
|
pidl "\t\tif (dce_call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {\n";
|
||||||
|
pidl "\t\t\tDEBUG(5,(\"function $fn->{NAME} will reply async\\n\"));\n";
|
||||||
|
pidl "\t\t}\n";
|
||||||
|
pidl "\t\tbreak;\n\t}\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#####################################################
|
||||||
|
# generate the switch statement for function reply
|
||||||
|
sub gen_reply_switch($)
|
||||||
|
{
|
||||||
|
my $interface = shift;
|
||||||
|
|
||||||
|
foreach my $fn (@{$interface->{FUNCTIONS}}) {
|
||||||
|
next if not defined($fn->{OPNUM});
|
||||||
|
|
||||||
|
pidl "\tcase $fn->{OPNUM}: {\n";
|
||||||
|
pidl "\t\tstruct $fn->{NAME} *r2 = (struct $fn->{NAME} *)r;\n";
|
||||||
|
pidl "\t\tif (dce_call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {\n";
|
||||||
|
pidl "\t\t\tDEBUG(5,(\"function $fn->{NAME} replied async\\n\"));\n";
|
||||||
|
pidl "\t\t}\n";
|
||||||
|
pidl "\t\tif (DEBUGLEVEL >= 10 && dce_call->fault_code == 0) {\n";
|
||||||
|
pidl "\t\t\tNDR_PRINT_FUNCTION_DEBUG($fn->{NAME}, NDR_OUT | NDR_SET_VALUES, r2);\n";
|
||||||
|
pidl "\t\t}\n";
|
||||||
|
pidl "\t\tif (dce_call->fault_code != 0) {\n";
|
||||||
|
pidl "\t\t\tDEBUG(2,(\"dcerpc_fault %s in $fn->{NAME}\\n\", dcerpc_errstr(mem_ctx, dce_call->fault_code)));\n";
|
||||||
|
pidl "\t\t}\n";
|
||||||
|
pidl "\t\tbreak;\n\t}\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#####################################################################
|
||||||
|
# produce boilerplate code for a interface
|
||||||
|
sub Boilerplate_Iface($)
|
||||||
|
{
|
||||||
|
my($interface) = shift;
|
||||||
|
my $name = $interface->{NAME};
|
||||||
|
my $uname = uc $name;
|
||||||
|
my $uuid = lc($interface->{UUID});
|
||||||
|
my $if_version = $interface->{VERSION};
|
||||||
|
|
||||||
|
pidl "
|
||||||
|
static NTSTATUS $name\__op_bind(struct dcesrv_call_state *dce_call, const struct dcesrv_interface *iface, uint32_t if_version)
|
||||||
|
{
|
||||||
|
#ifdef DCESRV_INTERFACE_$uname\_BIND
|
||||||
|
return DCESRV_INTERFACE_$uname\_BIND(dce_call,iface);
|
||||||
|
#else
|
||||||
|
return NT_STATUS_OK;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static void $name\__op_unbind(struct dcesrv_connection_context *context, const struct dcesrv_interface *iface)
|
||||||
|
{
|
||||||
|
#ifdef DCESRV_INTERFACE_$uname\_UNBIND
|
||||||
|
DCESRV_INTERFACE_$uname\_UNBIND(context, iface);
|
||||||
|
#else
|
||||||
|
return;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static NTSTATUS $name\__op_ndr_pull(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct ndr_pull *pull, void **r)
|
||||||
|
{
|
||||||
|
enum ndr_err_code ndr_err;
|
||||||
|
uint16_t opnum = dce_call->pkt.u.request.opnum;
|
||||||
|
|
||||||
|
dce_call->fault_code = 0;
|
||||||
|
|
||||||
|
if (opnum >= ndr_table_$name.num_calls) {
|
||||||
|
dce_call->fault_code = DCERPC_FAULT_OP_RNG_ERROR;
|
||||||
|
return NT_STATUS_NET_WRITE_FAULT;
|
||||||
|
}
|
||||||
|
|
||||||
|
*r = talloc_named(mem_ctx,
|
||||||
|
ndr_table_$name.calls[opnum].struct_size,
|
||||||
|
\"struct %s\",
|
||||||
|
ndr_table_$name.calls[opnum].name);
|
||||||
|
NT_STATUS_HAVE_NO_MEMORY(*r);
|
||||||
|
|
||||||
|
/* unravel the NDR for the packet */
|
||||||
|
ndr_err = ndr_table_$name.calls[opnum].ndr_pull(pull, NDR_IN, *r);
|
||||||
|
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
|
||||||
|
dcerpc_log_packet(dce_call->conn->packet_log_dir,
|
||||||
|
&ndr_table_$name, opnum, NDR_IN,
|
||||||
|
&dce_call->pkt.u.request.stub_and_verifier);
|
||||||
|
dce_call->fault_code = DCERPC_FAULT_NDR;
|
||||||
|
return NT_STATUS_NET_WRITE_FAULT;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NT_STATUS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static NTSTATUS $name\__op_dispatch(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, void *r)
|
||||||
|
{
|
||||||
|
uint16_t opnum = dce_call->pkt.u.request.opnum;
|
||||||
|
|
||||||
|
switch (opnum) {
|
||||||
|
";
|
||||||
|
gen_dispatch_switch($interface);
|
||||||
|
|
||||||
|
pidl "
|
||||||
|
default:
|
||||||
|
dce_call->fault_code = DCERPC_FAULT_OP_RNG_ERROR;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dce_call->fault_code != 0) {
|
||||||
|
dcerpc_log_packet(dce_call->conn->packet_log_dir,
|
||||||
|
&ndr_table_$name, opnum, NDR_IN,
|
||||||
|
&dce_call->pkt.u.request.stub_and_verifier);
|
||||||
|
return NT_STATUS_NET_WRITE_FAULT;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NT_STATUS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static NTSTATUS $name\__op_reply(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, void *r)
|
||||||
|
{
|
||||||
|
uint16_t opnum = dce_call->pkt.u.request.opnum;
|
||||||
|
|
||||||
|
switch (opnum) {
|
||||||
|
";
|
||||||
|
gen_reply_switch($interface);
|
||||||
|
|
||||||
|
pidl "
|
||||||
|
default:
|
||||||
|
dce_call->fault_code = DCERPC_FAULT_OP_RNG_ERROR;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dce_call->fault_code != 0) {
|
||||||
|
dcerpc_log_packet(dce_call->conn->packet_log_dir,
|
||||||
|
&ndr_table_$name, opnum, NDR_IN,
|
||||||
|
&dce_call->pkt.u.request.stub_and_verifier);
|
||||||
|
return NT_STATUS_NET_WRITE_FAULT;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NT_STATUS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static NTSTATUS $name\__op_ndr_push(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct ndr_push *push, const void *r)
|
||||||
|
{
|
||||||
|
enum ndr_err_code ndr_err;
|
||||||
|
uint16_t opnum = dce_call->pkt.u.request.opnum;
|
||||||
|
|
||||||
|
ndr_err = ndr_table_$name.calls[opnum].ndr_push(push, NDR_OUT, r);
|
||||||
|
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
|
||||||
|
dce_call->fault_code = DCERPC_FAULT_NDR;
|
||||||
|
return NT_STATUS_NET_WRITE_FAULT;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NT_STATUS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
const struct dcesrv_interface dcesrv\_$name\_interface = {
|
||||||
|
.name = \"$name\",
|
||||||
|
.syntax_id = {".print_uuid($uuid).",$if_version},
|
||||||
|
.bind = $name\__op_bind,
|
||||||
|
.unbind = $name\__op_unbind,
|
||||||
|
.ndr_pull = $name\__op_ndr_pull,
|
||||||
|
.dispatch = $name\__op_dispatch,
|
||||||
|
.reply = $name\__op_reply,
|
||||||
|
.ndr_push = $name\__op_ndr_push
|
||||||
|
};
|
||||||
|
|
||||||
|
";
|
||||||
|
}
|
||||||
|
|
||||||
|
#####################################################################
|
||||||
|
# produce boilerplate code for an endpoint server
|
||||||
|
sub Boilerplate_Ep_Server($)
|
||||||
|
{
|
||||||
|
my($interface) = shift;
|
||||||
|
my $name = $interface->{NAME};
|
||||||
|
my $uname = uc $name;
|
||||||
|
|
||||||
|
pidl "
|
||||||
|
static NTSTATUS $name\__op_init_server(struct dcesrv_context *dce_ctx, const struct dcesrv_endpoint_server *ep_server)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i=0;i<ndr_table_$name.endpoints->count;i++) {
|
||||||
|
NTSTATUS ret;
|
||||||
|
const char *name = ndr_table_$name.endpoints->names[i];
|
||||||
|
|
||||||
|
ret = dcesrv_interface_register(dce_ctx, name, &dcesrv_$name\_interface, NULL);
|
||||||
|
if (!NT_STATUS_IS_OK(ret)) {
|
||||||
|
DEBUG(1,(\"$name\_op_init_server: failed to register endpoint \'%s\'\\n\",name));
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NT_STATUS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool $name\__op_interface_by_uuid(struct dcesrv_interface *iface, const struct GUID *uuid, uint32_t if_version)
|
||||||
|
{
|
||||||
|
if (dcesrv_$name\_interface.syntax_id.if_version == if_version &&
|
||||||
|
GUID_equal(\&dcesrv\_$name\_interface.syntax_id.uuid, uuid)) {
|
||||||
|
memcpy(iface,&dcesrv\_$name\_interface, sizeof(*iface));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool $name\__op_interface_by_name(struct dcesrv_interface *iface, const char *name)
|
||||||
|
{
|
||||||
|
if (strcmp(dcesrv_$name\_interface.name, name)==0) {
|
||||||
|
memcpy(iface, &dcesrv_$name\_interface, sizeof(*iface));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
NTSTATUS dcerpc_server_$name\_init(void)
|
||||||
|
{
|
||||||
|
NTSTATUS ret;
|
||||||
|
struct dcesrv_endpoint_server ep_server;
|
||||||
|
|
||||||
|
/* fill in our name */
|
||||||
|
ep_server.name = \"$name\";
|
||||||
|
|
||||||
|
/* fill in all the operations */
|
||||||
|
ep_server.init_server = $name\__op_init_server;
|
||||||
|
|
||||||
|
ep_server.interface_by_uuid = $name\__op_interface_by_uuid;
|
||||||
|
ep_server.interface_by_name = $name\__op_interface_by_name;
|
||||||
|
|
||||||
|
/* register ourselves with the DCERPC subsystem. */
|
||||||
|
ret = dcerpc_register_ep_server(&ep_server);
|
||||||
|
|
||||||
|
if (!NT_STATUS_IS_OK(ret)) {
|
||||||
|
DEBUG(0,(\"Failed to register \'$name\' endpoint server!\\n\"));
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
";
|
||||||
|
}
|
||||||
|
|
||||||
|
#####################################################################
|
||||||
|
# dcerpc server boilerplate from a parsed IDL structure
|
||||||
|
sub ParseInterface($)
|
||||||
|
{
|
||||||
|
my($interface) = shift;
|
||||||
|
my $count = 0;
|
||||||
|
|
||||||
|
$res .= "NTSTATUS dcerpc_server_$interface->{NAME}\_init(void);\n";
|
||||||
|
$res .= "\n";
|
||||||
|
|
||||||
|
if (!defined $interface->{PROPERTIES}->{uuid}) {
|
||||||
|
return $res;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!defined $interface->{PROPERTIES}->{version}) {
|
||||||
|
$interface->{PROPERTIES}->{version} = "0.0";
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach my $fn (@{$interface->{FUNCTIONS}}) {
|
||||||
|
if (defined($fn->{OPNUM})) { $count++; }
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($count == 0) {
|
||||||
|
return $res;
|
||||||
|
}
|
||||||
|
|
||||||
|
$res .= "/* $interface->{NAME} - dcerpc server boilerplate generated by pidl */\n\n";
|
||||||
|
Boilerplate_Iface($interface);
|
||||||
|
Boilerplate_Ep_Server($interface);
|
||||||
|
|
||||||
|
return $res;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub Parse($$)
|
||||||
|
{
|
||||||
|
my($ndr,$header) = @_;
|
||||||
|
|
||||||
|
$res = "";
|
||||||
|
$res .= "/* server functions auto-generated by pidl */\n";
|
||||||
|
$res .= "#include \"$header\"\n";
|
||||||
|
$res .= "\n";
|
||||||
|
|
||||||
|
foreach my $x (@{$ndr}) {
|
||||||
|
ParseInterface($x) if ($x->{TYPE} eq "INTERFACE" and not defined($x->{PROPERTIES}{object}));
|
||||||
|
}
|
||||||
|
|
||||||
|
return $res;
|
||||||
|
}
|
||||||
|
|
||||||
|
1;
|
1448
tools/pidl/lib/Parse/Pidl/Samba4/Python.pm
Normal file
1448
tools/pidl/lib/Parse/Pidl/Samba4/Python.pm
Normal file
File diff suppressed because it is too large
Load Diff
283
tools/pidl/lib/Parse/Pidl/Samba4/TDR.pm
Normal file
283
tools/pidl/lib/Parse/Pidl/Samba4/TDR.pm
Normal file
|
@ -0,0 +1,283 @@
|
||||||
|
###################################################
|
||||||
|
# Trivial Parser Generator
|
||||||
|
# Copyright jelmer@samba.org 2005-2007
|
||||||
|
# released under the GNU GPL
|
||||||
|
|
||||||
|
package Parse::Pidl::Samba4::TDR;
|
||||||
|
use Parse::Pidl qw(fatal);
|
||||||
|
use Parse::Pidl::Util qw(has_property ParseExpr is_constant);
|
||||||
|
use Parse::Pidl::Samba4 qw(is_intree choose_header);
|
||||||
|
use Parse::Pidl::Typelist qw(mapTypeName);
|
||||||
|
|
||||||
|
use Exporter;
|
||||||
|
@ISA = qw(Exporter);
|
||||||
|
@EXPORT_OK = qw(ParserType $ret $ret_hdr);
|
||||||
|
|
||||||
|
use vars qw($VERSION);
|
||||||
|
$VERSION = '0.01';
|
||||||
|
|
||||||
|
use strict;
|
||||||
|
|
||||||
|
sub new($) {
|
||||||
|
my ($class) = shift;
|
||||||
|
my $self = { ret => "", ret_hdr => "", tabs => "" };
|
||||||
|
bless($self, $class);
|
||||||
|
}
|
||||||
|
|
||||||
|
sub indent($) { my $self = shift; $self->{tabs}.="\t"; }
|
||||||
|
sub deindent($) { my $self = shift; $self->{tabs} = substr($self->{tabs}, 1); }
|
||||||
|
sub pidl($$) { my $self = shift; $self->{ret} .= $self->{tabs}.(shift)."\n"; }
|
||||||
|
sub pidl_hdr($$) { my $self = shift; $self->{ret_hdr} .= (shift)."\n"; }
|
||||||
|
sub typearg($) {
|
||||||
|
my $t = shift;
|
||||||
|
return(", const char *name") if ($t eq "print");
|
||||||
|
return(", TALLOC_CTX *mem_ctx") if ($t eq "pull");
|
||||||
|
return("");
|
||||||
|
}
|
||||||
|
|
||||||
|
sub fn_declare($$$)
|
||||||
|
{
|
||||||
|
my ($self, $p, $d) = @_;
|
||||||
|
if ($p) {
|
||||||
|
$self->pidl($d); $self->pidl_hdr("$d;");
|
||||||
|
} else {
|
||||||
|
$self->pidl("static $d");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sub ContainsArray($)
|
||||||
|
{
|
||||||
|
my $e = shift;
|
||||||
|
foreach (@{$e->{ELEMENTS}}) {
|
||||||
|
next if (has_property($_, "charset") and
|
||||||
|
scalar(@{$_->{ARRAY_LEN}}) == 1);
|
||||||
|
return 1 if (defined($_->{ARRAY_LEN}) and
|
||||||
|
scalar(@{$_->{ARRAY_LEN}}) > 0);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub ParserElement($$$$)
|
||||||
|
{
|
||||||
|
my ($self, $e,$t,$env) = @_;
|
||||||
|
my $switch = "";
|
||||||
|
my $array = "";
|
||||||
|
my $name = "";
|
||||||
|
my $mem_ctx = "mem_ctx";
|
||||||
|
|
||||||
|
fatal($e,"Pointers not supported in TDR") if ($e->{POINTERS} > 0);
|
||||||
|
fatal($e,"size_is() not supported in TDR") if (has_property($e, "size_is"));
|
||||||
|
fatal($e,"length_is() not supported in TDR") if (has_property($e, "length_is"));
|
||||||
|
|
||||||
|
if ($t eq "print") {
|
||||||
|
$name = ", \"$e->{NAME}\"$array";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (has_property($e, "flag")) {
|
||||||
|
$self->pidl("{");
|
||||||
|
$self->indent;
|
||||||
|
$self->pidl("uint32_t saved_flags = tdr->flags;");
|
||||||
|
$self->pidl("tdr->flags |= $e->{PROPERTIES}->{flag};");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (has_property($e, "charset")) {
|
||||||
|
fatal($e,"charset() on non-array element") unless (defined($e->{ARRAY_LEN}) and scalar(@{$e->{ARRAY_LEN}}) > 0);
|
||||||
|
|
||||||
|
my $len = ParseExpr(@{$e->{ARRAY_LEN}}[0], $env, $e);
|
||||||
|
if ($len eq "*") { $len = "-1"; }
|
||||||
|
$name = ", mem_ctx" if ($t eq "pull");
|
||||||
|
$self->pidl("TDR_CHECK(tdr_$t\_charset(tdr$name, &v->$e->{NAME}, $len, sizeof($e->{TYPE}_t), CH_$e->{PROPERTIES}->{charset}));");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (has_property($e, "switch_is")) {
|
||||||
|
$switch = ", " . ParseExpr($e->{PROPERTIES}->{switch_is}, $env, $e);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (defined($e->{ARRAY_LEN}) and scalar(@{$e->{ARRAY_LEN}}) > 0) {
|
||||||
|
my $len = ParseExpr($e->{ARRAY_LEN}[0], $env, $e);
|
||||||
|
|
||||||
|
if ($t eq "pull" and not is_constant($len)) {
|
||||||
|
$self->pidl("TDR_ALLOC(mem_ctx, v->$e->{NAME}, $len);");
|
||||||
|
$mem_ctx = "v->$e->{NAME}";
|
||||||
|
}
|
||||||
|
|
||||||
|
$self->pidl("for (i = 0; i < $len; i++) {");
|
||||||
|
$self->indent;
|
||||||
|
$array = "[i]";
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($t eq "pull") {
|
||||||
|
$name = ", $mem_ctx";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (has_property($e, "value") && $t eq "push") {
|
||||||
|
$self->pidl("v->$e->{NAME} = ".ParseExpr($e->{PROPERTIES}->{value}, $env, $e).";");
|
||||||
|
}
|
||||||
|
|
||||||
|
$self->pidl("TDR_CHECK(tdr_$t\_$e->{TYPE}(tdr$name$switch, &v->$e->{NAME}$array));");
|
||||||
|
|
||||||
|
if ($array) { $self->deindent; $self->pidl("}"); }
|
||||||
|
|
||||||
|
if (has_property($e, "flag")) {
|
||||||
|
$self->pidl("tdr->flags = saved_flags;");
|
||||||
|
$self->deindent;
|
||||||
|
$self->pidl("}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sub ParserStruct($$$$$)
|
||||||
|
{
|
||||||
|
my ($self, $e,$t,$p) = @_;
|
||||||
|
|
||||||
|
$self->fn_declare($p,"NTSTATUS tdr_$t\_$e->{NAME} (struct tdr_$t *tdr".typearg($t).", struct $e->{NAME} *v)");
|
||||||
|
$self->pidl("{"); $self->indent;
|
||||||
|
$self->pidl("int i;") if (ContainsArray($e));
|
||||||
|
|
||||||
|
if ($t eq "print") {
|
||||||
|
$self->pidl("tdr->print(tdr, \"\%-25s: struct $e->{NAME}\", name);");
|
||||||
|
$self->pidl("tdr->level++;");
|
||||||
|
}
|
||||||
|
|
||||||
|
my %env = map { $_->{NAME} => "v->$_->{NAME}" } @{$e->{ELEMENTS}};
|
||||||
|
$env{"this"} = "v";
|
||||||
|
$self->ParserElement($_, $t, \%env) foreach (@{$e->{ELEMENTS}});
|
||||||
|
|
||||||
|
if ($t eq "print") {
|
||||||
|
$self->pidl("tdr->level--;");
|
||||||
|
}
|
||||||
|
|
||||||
|
$self->pidl("return NT_STATUS_OK;");
|
||||||
|
|
||||||
|
$self->deindent; $self->pidl("}");
|
||||||
|
}
|
||||||
|
|
||||||
|
sub ParserUnion($$$$)
|
||||||
|
{
|
||||||
|
my ($self, $e,$t,$p) = @_;
|
||||||
|
|
||||||
|
$self->fn_declare($p,"NTSTATUS tdr_$t\_$e->{NAME}(struct tdr_$t *tdr".typearg($t).", int level, union $e->{NAME} *v)");
|
||||||
|
$self->pidl("{"); $self->indent;
|
||||||
|
$self->pidl("int i;") if (ContainsArray($e));
|
||||||
|
|
||||||
|
if ($t eq "print") {
|
||||||
|
$self->pidl("tdr->print(tdr, \"\%-25s: union $e->{NAME}\", name);");
|
||||||
|
$self->pidl("tdr->level++;");
|
||||||
|
}
|
||||||
|
|
||||||
|
$self->pidl("switch (level) {"); $self->indent;
|
||||||
|
foreach (@{$e->{ELEMENTS}}) {
|
||||||
|
if (has_property($_, "case")) {
|
||||||
|
$self->pidl("case " . $_->{PROPERTIES}->{case} . ":");
|
||||||
|
} elsif (has_property($_, "default")) {
|
||||||
|
$self->pidl("default:");
|
||||||
|
}
|
||||||
|
$self->indent; $self->ParserElement($_, $t, {}); $self->deindent;
|
||||||
|
$self->pidl("break;");
|
||||||
|
}
|
||||||
|
$self->deindent; $self->pidl("}");
|
||||||
|
|
||||||
|
if ($t eq "print") {
|
||||||
|
$self->pidl("tdr->level--;");
|
||||||
|
}
|
||||||
|
|
||||||
|
$self->pidl("return NT_STATUS_OK;\n");
|
||||||
|
$self->deindent; $self->pidl("}");
|
||||||
|
}
|
||||||
|
|
||||||
|
sub ParserBitmap($$$$)
|
||||||
|
{
|
||||||
|
my ($self,$e,$t,$p) = @_;
|
||||||
|
return if ($p);
|
||||||
|
$self->pidl("#define tdr_$t\_$e->{NAME} tdr_$t\_" . Parse::Pidl::Typelist::bitmap_type_fn($e));
|
||||||
|
}
|
||||||
|
|
||||||
|
sub ParserEnum($$$$)
|
||||||
|
{
|
||||||
|
my ($self,$e,$t,$p) = @_;
|
||||||
|
my $bt = Parse::Pidl::Typelist::enum_type_fn($e);
|
||||||
|
my $mt = mapTypeName($bt);
|
||||||
|
|
||||||
|
$self->fn_declare($p, "NTSTATUS tdr_$t\_$e->{NAME} (struct tdr_$t *tdr".typearg($t).", enum $e->{NAME} *v)");
|
||||||
|
$self->pidl("{");
|
||||||
|
if ($t eq "pull") {
|
||||||
|
$self->pidl("\t$mt r;");
|
||||||
|
$self->pidl("\tTDR_CHECK(tdr_$t\_$bt(tdr, mem_ctx, \&r));");
|
||||||
|
$self->pidl("\t*v = r;");
|
||||||
|
} elsif ($t eq "push") {
|
||||||
|
$self->pidl("\tTDR_CHECK(tdr_$t\_$bt(tdr, ($mt *)v));");
|
||||||
|
} elsif ($t eq "print") {
|
||||||
|
$self->pidl("\t/* FIXME */");
|
||||||
|
}
|
||||||
|
$self->pidl("\treturn NT_STATUS_OK;");
|
||||||
|
$self->pidl("}");
|
||||||
|
}
|
||||||
|
|
||||||
|
sub ParserTypedef($$$$)
|
||||||
|
{
|
||||||
|
my ($self, $e,$t,$p) = @_;
|
||||||
|
|
||||||
|
$self->ParserType($e->{DATA},$t);
|
||||||
|
}
|
||||||
|
|
||||||
|
sub ParserType($$$)
|
||||||
|
{
|
||||||
|
my ($self, $e,$t) = @_;
|
||||||
|
|
||||||
|
return if (has_property($e, "no$t"));
|
||||||
|
|
||||||
|
my $handlers = {
|
||||||
|
STRUCT => \&ParserStruct, UNION => \&ParserUnion,
|
||||||
|
ENUM => \&ParserEnum, BITMAP => \&ParserBitmap,
|
||||||
|
TYPEDEF => \&ParserTypedef
|
||||||
|
};
|
||||||
|
|
||||||
|
$handlers->{$e->{TYPE}}->($self, $e, $t, has_property($e, "public"))
|
||||||
|
if (defined($handlers->{$e->{TYPE}}));
|
||||||
|
|
||||||
|
$self->pidl("");
|
||||||
|
}
|
||||||
|
|
||||||
|
sub ParserInterface($$)
|
||||||
|
{
|
||||||
|
my ($self,$x) = @_;
|
||||||
|
|
||||||
|
$self->pidl_hdr("#ifndef __TDR_$x->{NAME}_HEADER__");
|
||||||
|
$self->pidl_hdr("#define __TDR_$x->{NAME}_HEADER__");
|
||||||
|
|
||||||
|
foreach (@{$x->{DATA}}) {
|
||||||
|
$self->ParserType($_, "pull");
|
||||||
|
$self->ParserType($_, "push");
|
||||||
|
$self->ParserType($_, "print");
|
||||||
|
}
|
||||||
|
|
||||||
|
$self->pidl_hdr("#endif /* __TDR_$x->{NAME}_HEADER__ */");
|
||||||
|
}
|
||||||
|
|
||||||
|
sub Parser($$$$)
|
||||||
|
{
|
||||||
|
my ($self,$idl,$hdrname,$baseheader) = @_;
|
||||||
|
$self->pidl("/* autogenerated by pidl */");
|
||||||
|
if (is_intree()) {
|
||||||
|
$self->pidl("#include \"includes.h\"");
|
||||||
|
} else {
|
||||||
|
$self->pidl("#include <stdio.h>");
|
||||||
|
$self->pidl("#include <stdbool.h>");
|
||||||
|
$self->pidl("#include <stdlib.h>");
|
||||||
|
$self->pidl("#include <stdint.h>");
|
||||||
|
$self->pidl("#include <stdarg.h>");
|
||||||
|
$self->pidl("#include <string.h>");
|
||||||
|
$self->pidl("#include <core/ntstatus.h>");
|
||||||
|
}
|
||||||
|
$self->pidl("#include \"$hdrname\"");
|
||||||
|
$self->pidl("");
|
||||||
|
$self->pidl_hdr("/* autogenerated by pidl */");
|
||||||
|
$self->pidl_hdr("#include \"$baseheader\"");
|
||||||
|
$self->pidl_hdr(choose_header("lib/tdr/tdr.h", "tdr.h"));
|
||||||
|
$self->pidl_hdr("");
|
||||||
|
|
||||||
|
foreach (@$idl) { $self->ParserInterface($_) if ($_->{TYPE} eq "INTERFACE"); }
|
||||||
|
return ($self->{ret_hdr}, $self->{ret});
|
||||||
|
}
|
||||||
|
|
||||||
|
1;
|
98
tools/pidl/lib/Parse/Pidl/Samba4/Template.pm
Normal file
98
tools/pidl/lib/Parse/Pidl/Samba4/Template.pm
Normal file
|
@ -0,0 +1,98 @@
|
||||||
|
###################################################
|
||||||
|
# server template function generator
|
||||||
|
# Copyright tridge@samba.org 2003
|
||||||
|
# released under the GNU GPL
|
||||||
|
|
||||||
|
package Parse::Pidl::Samba4::Template;
|
||||||
|
|
||||||
|
use vars qw($VERSION);
|
||||||
|
$VERSION = '0.01';
|
||||||
|
|
||||||
|
use strict;
|
||||||
|
|
||||||
|
my($res);
|
||||||
|
|
||||||
|
#####################################################################
|
||||||
|
# produce boilerplate code for a interface
|
||||||
|
sub Template($)
|
||||||
|
{
|
||||||
|
my($interface) = shift;
|
||||||
|
my($data) = $interface->{DATA};
|
||||||
|
my $name = $interface->{NAME};
|
||||||
|
|
||||||
|
$res .=
|
||||||
|
"/*
|
||||||
|
Unix SMB/CIFS implementation.
|
||||||
|
|
||||||
|
endpoint server for the $name pipe
|
||||||
|
|
||||||
|
Copyright (C) YOUR NAME HERE YEAR
|
||||||
|
|
||||||
|
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 3 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, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include \"includes.h\"
|
||||||
|
#include \"rpc_server/dcerpc_server.h\"
|
||||||
|
#include \"librpc/gen_ndr/ndr_$name.h\"
|
||||||
|
#include \"rpc_server/common/common.h\"
|
||||||
|
|
||||||
|
";
|
||||||
|
|
||||||
|
foreach my $d (@{$data}) {
|
||||||
|
if ($d->{TYPE} eq "FUNCTION") {
|
||||||
|
my $fname = $d->{NAME};
|
||||||
|
$res .=
|
||||||
|
"
|
||||||
|
/*
|
||||||
|
$fname
|
||||||
|
*/
|
||||||
|
static $d->{RETURN_TYPE} dcesrv_$fname(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
|
||||||
|
struct $fname *r)
|
||||||
|
{
|
||||||
|
";
|
||||||
|
|
||||||
|
if ($d->{RETURN_TYPE} eq "void") {
|
||||||
|
$res .= "\tDCESRV_FAULT_VOID(DCERPC_FAULT_OP_RNG_ERROR);\n";
|
||||||
|
} else {
|
||||||
|
$res .= "\tDCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
$res .= "}
|
||||||
|
|
||||||
|
";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$res .=
|
||||||
|
"
|
||||||
|
/* include the generated boilerplate */
|
||||||
|
#include \"librpc/gen_ndr/ndr_$name\_s.c\"
|
||||||
|
"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#####################################################################
|
||||||
|
# parse a parsed IDL structure back into an IDL file
|
||||||
|
sub Parse($)
|
||||||
|
{
|
||||||
|
my($idl) = shift;
|
||||||
|
$res = "";
|
||||||
|
foreach my $x (@{$idl}) {
|
||||||
|
($x->{TYPE} eq "INTERFACE") &&
|
||||||
|
Template($x);
|
||||||
|
}
|
||||||
|
return $res;
|
||||||
|
}
|
||||||
|
|
||||||
|
1;
|
372
tools/pidl/lib/Parse/Pidl/Typelist.pm
Normal file
372
tools/pidl/lib/Parse/Pidl/Typelist.pm
Normal file
|
@ -0,0 +1,372 @@
|
||||||
|
###################################################
|
||||||
|
# Samba4 parser generator for IDL structures
|
||||||
|
# Copyright jelmer@samba.org 2005
|
||||||
|
# released under the GNU GPL
|
||||||
|
|
||||||
|
package Parse::Pidl::Typelist;
|
||||||
|
|
||||||
|
require Exporter;
|
||||||
|
@ISA = qw(Exporter);
|
||||||
|
@EXPORT_OK = qw(hasType getType resolveType mapTypeName scalar_is_reference expandAlias
|
||||||
|
mapScalarType maybeMapScalarType addType typeIs is_signed is_scalar is_struct enum_type_fn
|
||||||
|
bitmap_type_fn mapType typeHasBody is_fixed_size_scalar
|
||||||
|
);
|
||||||
|
use vars qw($VERSION);
|
||||||
|
$VERSION = '0.01';
|
||||||
|
|
||||||
|
use Parse::Pidl::Util qw(has_property);
|
||||||
|
use strict;
|
||||||
|
|
||||||
|
my %types = ();
|
||||||
|
|
||||||
|
my @reference_scalars = (
|
||||||
|
"string", "string_array", "nbt_string", "dns_string",
|
||||||
|
"wrepl_nbt_name", "dnsp_name", "dnsp_string",
|
||||||
|
"ipv4address", "ipv6address"
|
||||||
|
);
|
||||||
|
|
||||||
|
my @non_fixed_size_scalars = (
|
||||||
|
"string", "string_array", "nbt_string", "dns_string",
|
||||||
|
"wrepl_nbt_name", "dnsp_name", "dnsp_string"
|
||||||
|
);
|
||||||
|
|
||||||
|
# a list of known scalar types
|
||||||
|
my %scalars = (
|
||||||
|
"void" => "void",
|
||||||
|
"char" => "char",
|
||||||
|
"int8" => "int8_t",
|
||||||
|
"uint8" => "uint8_t",
|
||||||
|
"int16" => "int16_t",
|
||||||
|
"uint16" => "uint16_t",
|
||||||
|
"int1632" => "int16_t",
|
||||||
|
"uint1632" => "uint16_t",
|
||||||
|
"int32" => "int32_t",
|
||||||
|
"uint32" => "uint32_t",
|
||||||
|
"int3264" => "int32_t",
|
||||||
|
"uint3264" => "uint32_t",
|
||||||
|
"hyper" => "uint64_t",
|
||||||
|
"dlong" => "int64_t",
|
||||||
|
"udlong" => "uint64_t",
|
||||||
|
"udlongr" => "uint64_t",
|
||||||
|
"double" => "double",
|
||||||
|
"pointer" => "void*",
|
||||||
|
"DATA_BLOB" => "DATA_BLOB",
|
||||||
|
"string" => "const char *",
|
||||||
|
"string_array" => "const char **",
|
||||||
|
"time_t" => "time_t",
|
||||||
|
"uid_t" => "uid_t",
|
||||||
|
"gid_t" => "gid_t",
|
||||||
|
"NTTIME" => "NTTIME",
|
||||||
|
"NTTIME_1sec" => "NTTIME",
|
||||||
|
"NTTIME_hyper" => "NTTIME",
|
||||||
|
"WERROR" => "WERROR",
|
||||||
|
"NTSTATUS" => "NTSTATUS",
|
||||||
|
"HRESULT" => "HRESULT",
|
||||||
|
"COMRESULT" => "COMRESULT",
|
||||||
|
"dns_string" => "const char *",
|
||||||
|
"nbt_string" => "const char *",
|
||||||
|
"wrepl_nbt_name"=> "struct nbt_name *",
|
||||||
|
"ipv4address" => "const char *",
|
||||||
|
"ipv6address" => "const char *",
|
||||||
|
"dnsp_name" => "const char *",
|
||||||
|
"dnsp_string" => "const char *",
|
||||||
|
);
|
||||||
|
|
||||||
|
my %aliases = (
|
||||||
|
"error_status_t" => "uint32",
|
||||||
|
"boolean8" => "uint8",
|
||||||
|
"boolean32" => "uint32",
|
||||||
|
"DWORD" => "uint32",
|
||||||
|
"uint" => "uint32",
|
||||||
|
"int" => "int32",
|
||||||
|
"WORD" => "uint16",
|
||||||
|
"char" => "uint8",
|
||||||
|
"long" => "int32",
|
||||||
|
"short" => "int16",
|
||||||
|
"HYPER_T" => "hyper",
|
||||||
|
"mode_t" => "uint32",
|
||||||
|
);
|
||||||
|
|
||||||
|
sub expandAlias($)
|
||||||
|
{
|
||||||
|
my $name = shift;
|
||||||
|
|
||||||
|
return $aliases{$name} if defined($aliases{$name});
|
||||||
|
|
||||||
|
return $name;
|
||||||
|
}
|
||||||
|
|
||||||
|
# map from a IDL type to a C header type
|
||||||
|
sub mapScalarType($)
|
||||||
|
{
|
||||||
|
my $name = shift;
|
||||||
|
|
||||||
|
# it's a bug when a type is not in the list
|
||||||
|
# of known scalars or has no mapping
|
||||||
|
return $scalars{$name} if defined($scalars{$name});
|
||||||
|
|
||||||
|
die("Unknown scalar type $name");
|
||||||
|
}
|
||||||
|
|
||||||
|
sub maybeMapScalarType($)
|
||||||
|
{
|
||||||
|
my $name = shift;
|
||||||
|
return $scalars{$name} if defined($scalars{$name});
|
||||||
|
return $name;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub addType($)
|
||||||
|
{
|
||||||
|
my $t = shift;
|
||||||
|
$types{$t->{NAME}} = $t;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub resolveType($)
|
||||||
|
{
|
||||||
|
my ($ctype) = @_;
|
||||||
|
|
||||||
|
if (not hasType($ctype)) {
|
||||||
|
# assume struct typedef
|
||||||
|
return { TYPE => "TYPEDEF", NAME => $ctype, DATA => { TYPE => "STRUCT" } };
|
||||||
|
} else {
|
||||||
|
return getType($ctype);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $ctype;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub getType($)
|
||||||
|
{
|
||||||
|
my $t = shift;
|
||||||
|
return ($t) if (ref($t) eq "HASH" and not defined($t->{NAME}));
|
||||||
|
return undef if not hasType($t);
|
||||||
|
return $types{$t->{NAME}} if (ref($t) eq "HASH");
|
||||||
|
return $types{$t};
|
||||||
|
}
|
||||||
|
|
||||||
|
sub typeIs($$);
|
||||||
|
sub typeIs($$)
|
||||||
|
{
|
||||||
|
my ($t,$tt) = @_;
|
||||||
|
|
||||||
|
if (ref($t) eq "HASH") {
|
||||||
|
return 1 if ($t->{TYPE} eq "TYPEDEF" and $t->{DATA}->{TYPE} eq $tt);
|
||||||
|
return 1 if ($t->{TYPE} eq $tt);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (hasType($t) and getType($t)->{TYPE} eq "TYPEDEF") {
|
||||||
|
return typeIs(getType($t)->{DATA}, $tt);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub hasType($)
|
||||||
|
{
|
||||||
|
my $t = shift;
|
||||||
|
if (ref($t) eq "HASH") {
|
||||||
|
return 1 if (not defined($t->{NAME}));
|
||||||
|
return 1 if (defined($types{$t->{NAME}}) and
|
||||||
|
$types{$t->{NAME}}->{TYPE} eq $t->{TYPE});
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return 1 if defined($types{$t});
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub is_signed($)
|
||||||
|
{
|
||||||
|
my $t = shift;
|
||||||
|
|
||||||
|
return ($t eq "int8"
|
||||||
|
or $t eq "int16"
|
||||||
|
or $t eq "int32"
|
||||||
|
or $t eq "dlong"
|
||||||
|
or $t eq "int"
|
||||||
|
or $t eq "long"
|
||||||
|
or $t eq "short");
|
||||||
|
}
|
||||||
|
|
||||||
|
sub is_scalar($)
|
||||||
|
{
|
||||||
|
sub is_scalar($);
|
||||||
|
my $type = shift;
|
||||||
|
|
||||||
|
return 1 if (ref($type) eq "HASH" and
|
||||||
|
($type->{TYPE} eq "SCALAR" or $type->{TYPE} eq "ENUM" or
|
||||||
|
$type->{TYPE} eq "BITMAP"));
|
||||||
|
|
||||||
|
if (my $dt = getType($type)) {
|
||||||
|
return is_scalar($dt->{DATA}) if ($dt->{TYPE} eq "TYPEDEF");
|
||||||
|
return 1 if ($dt->{TYPE} eq "SCALAR" or $dt->{TYPE} eq "ENUM" or
|
||||||
|
$dt->{TYPE} eq "BITMAP");
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub is_struct($)
|
||||||
|
{
|
||||||
|
my $type = shift;
|
||||||
|
return 1 if (ref($type) eq "HASH" and $type->{TYPE} eq "STRUCT");
|
||||||
|
if (my $dt = getType($type)) {
|
||||||
|
return is_struct($dt->{DATA}) if ($dt->{TYPE} eq "TYPEDEF");
|
||||||
|
return 1 if ($dt->{TYPE} eq "STRUCT");
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub is_fixed_size_scalar($)
|
||||||
|
{
|
||||||
|
my $name = shift;
|
||||||
|
|
||||||
|
return 0 unless is_scalar($name);
|
||||||
|
return 0 if (grep(/^$name$/, @non_fixed_size_scalars));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub scalar_is_reference($)
|
||||||
|
{
|
||||||
|
my $name = shift;
|
||||||
|
|
||||||
|
return 1 if (grep(/^$name$/, @reference_scalars));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub RegisterScalars()
|
||||||
|
{
|
||||||
|
foreach (keys %scalars) {
|
||||||
|
addType({
|
||||||
|
NAME => $_,
|
||||||
|
TYPE => "TYPEDEF",
|
||||||
|
BASEFILE => "<builtin>",
|
||||||
|
DATA => {
|
||||||
|
TYPE => "SCALAR",
|
||||||
|
NAME => $_
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sub enum_type_fn($)
|
||||||
|
{
|
||||||
|
my $enum = shift;
|
||||||
|
$enum->{TYPE} eq "ENUM" or die("not an enum");
|
||||||
|
|
||||||
|
# for typedef enum { } we need to check $enum->{PARENT}
|
||||||
|
if (has_property($enum, "enum8bit")) {
|
||||||
|
return "uint8";
|
||||||
|
} elsif (has_property($enum, "enum16bit")) {
|
||||||
|
return "uint16";
|
||||||
|
} elsif (has_property($enum, "v1_enum")) {
|
||||||
|
return "uint32";
|
||||||
|
} elsif (has_property($enum->{PARENT}, "enum8bit")) {
|
||||||
|
return "uint8";
|
||||||
|
} elsif (has_property($enum->{PARENT}, "enum16bit")) {
|
||||||
|
return "uint16";
|
||||||
|
} elsif (has_property($enum->{PARENT}, "v1_enum")) {
|
||||||
|
return "uint32";
|
||||||
|
}
|
||||||
|
return "uint1632";
|
||||||
|
}
|
||||||
|
|
||||||
|
sub bitmap_type_fn($)
|
||||||
|
{
|
||||||
|
my $bitmap = shift;
|
||||||
|
|
||||||
|
$bitmap->{TYPE} eq "BITMAP" or die("not a bitmap");
|
||||||
|
|
||||||
|
if (has_property($bitmap, "bitmap8bit")) {
|
||||||
|
return "uint8";
|
||||||
|
} elsif (has_property($bitmap, "bitmap16bit")) {
|
||||||
|
return "uint16";
|
||||||
|
} elsif (has_property($bitmap, "bitmap64bit")) {
|
||||||
|
return "hyper";
|
||||||
|
}
|
||||||
|
return "uint32";
|
||||||
|
}
|
||||||
|
|
||||||
|
sub typeHasBody($)
|
||||||
|
{
|
||||||
|
sub typeHasBody($);
|
||||||
|
my ($e) = @_;
|
||||||
|
|
||||||
|
if ($e->{TYPE} eq "TYPEDEF") {
|
||||||
|
return 0 unless(defined($e->{DATA}));
|
||||||
|
return typeHasBody($e->{DATA});
|
||||||
|
}
|
||||||
|
|
||||||
|
return defined($e->{ELEMENTS});
|
||||||
|
}
|
||||||
|
|
||||||
|
sub mapType($$)
|
||||||
|
{
|
||||||
|
sub mapType($$);
|
||||||
|
my ($t, $n) = @_;
|
||||||
|
|
||||||
|
return mapTypeName($t->{DATA}) if ($t->{TYPE} eq "TYPEDEF");
|
||||||
|
return mapScalarType($n) if ($t->{TYPE} eq "SCALAR");
|
||||||
|
return "enum $n" if ($t->{TYPE} eq "ENUM");
|
||||||
|
return "struct $n" if ($t->{TYPE} eq "STRUCT" or $t->{TYPE} eq "INTERFACE");
|
||||||
|
return "union $n" if ($t->{TYPE} eq "UNION");
|
||||||
|
return mapScalarType(bitmap_type_fn($t)) if ($t->{TYPE} eq "BITMAP");
|
||||||
|
return "struct $n" if ($t->{TYPE} eq "PIPE");
|
||||||
|
die("Unknown type $t->{TYPE}");
|
||||||
|
}
|
||||||
|
|
||||||
|
sub mapTypeName($)
|
||||||
|
{
|
||||||
|
my $t = shift;
|
||||||
|
return "void" unless defined($t);
|
||||||
|
my $dt;
|
||||||
|
$t = expandAlias($t);
|
||||||
|
|
||||||
|
if ($dt = getType($t)) {
|
||||||
|
return mapType($dt, $dt->{NAME});
|
||||||
|
} elsif (ref($t) eq "HASH" and defined($t->{NAME})) {
|
||||||
|
return mapType($t, $t->{NAME});
|
||||||
|
} else {
|
||||||
|
# Best guess
|
||||||
|
return "struct $t";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
sub LoadIdl($;$)
|
||||||
|
{
|
||||||
|
my $idl = shift;
|
||||||
|
my $basename = shift;
|
||||||
|
|
||||||
|
foreach my $x (@{$idl}) {
|
||||||
|
next if $x->{TYPE} ne "INTERFACE";
|
||||||
|
|
||||||
|
# DCOM interfaces can be types as well
|
||||||
|
addType({
|
||||||
|
NAME => $x->{NAME},
|
||||||
|
TYPE => "TYPEDEF",
|
||||||
|
DATA => $x,
|
||||||
|
BASEFILE => $basename,
|
||||||
|
}) if (has_property($x, "object"));
|
||||||
|
|
||||||
|
foreach my $y (@{$x->{DATA}}) {
|
||||||
|
if ($y->{TYPE} eq "TYPEDEF"
|
||||||
|
or $y->{TYPE} eq "UNION"
|
||||||
|
or $y->{TYPE} eq "STRUCT"
|
||||||
|
or $y->{TYPE} eq "ENUM"
|
||||||
|
or $y->{TYPE} eq "BITMAP"
|
||||||
|
or $y->{TYPE} eq "PIPE") {
|
||||||
|
$y->{BASEFILE} = $basename;
|
||||||
|
addType($y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sub GenerateTypeLib()
|
||||||
|
{
|
||||||
|
return Parse::Pidl::Util::MyDumper(\%types);
|
||||||
|
}
|
||||||
|
|
||||||
|
RegisterScalars();
|
||||||
|
|
||||||
|
1;
|
182
tools/pidl/lib/Parse/Pidl/Util.pm
Normal file
182
tools/pidl/lib/Parse/Pidl/Util.pm
Normal file
|
@ -0,0 +1,182 @@
|
||||||
|
###################################################
|
||||||
|
# utility functions to support pidl
|
||||||
|
# Copyright tridge@samba.org 2000
|
||||||
|
# released under the GNU GPL
|
||||||
|
package Parse::Pidl::Util;
|
||||||
|
|
||||||
|
require Exporter;
|
||||||
|
@ISA = qw(Exporter);
|
||||||
|
@EXPORT = qw(has_property property_matches ParseExpr ParseExprExt is_constant make_str unmake_str print_uuid MyDumper);
|
||||||
|
use vars qw($VERSION);
|
||||||
|
$VERSION = '0.01';
|
||||||
|
|
||||||
|
use strict;
|
||||||
|
|
||||||
|
use Parse::Pidl::Expr;
|
||||||
|
use Parse::Pidl qw(error);
|
||||||
|
|
||||||
|
=head1 NAME
|
||||||
|
|
||||||
|
Parse::Pidl::Util - Generic utility functions for pidl
|
||||||
|
|
||||||
|
=head1 SYNOPSIS
|
||||||
|
|
||||||
|
use Parse::Pidl::Util;
|
||||||
|
|
||||||
|
=head1 DESCRIPTION
|
||||||
|
|
||||||
|
Simple module that contains a couple of trivial helper functions
|
||||||
|
used throughout the various pidl modules.
|
||||||
|
|
||||||
|
=head1 FUNCTIONS
|
||||||
|
|
||||||
|
=over 4
|
||||||
|
|
||||||
|
=cut
|
||||||
|
|
||||||
|
=item B<MyDumper>
|
||||||
|
a dumper wrapper to prevent dependence on the Data::Dumper module
|
||||||
|
unless we actually need it
|
||||||
|
|
||||||
|
=cut
|
||||||
|
|
||||||
|
sub MyDumper($)
|
||||||
|
{
|
||||||
|
require Data::Dumper;
|
||||||
|
my $s = shift;
|
||||||
|
return Data::Dumper::Dumper($s);
|
||||||
|
}
|
||||||
|
|
||||||
|
=item B<has_property>
|
||||||
|
see if a pidl property list contains a given property
|
||||||
|
|
||||||
|
=cut
|
||||||
|
sub has_property($$)
|
||||||
|
{
|
||||||
|
my($e, $p) = @_;
|
||||||
|
|
||||||
|
return undef if (not defined($e->{PROPERTIES}));
|
||||||
|
|
||||||
|
return $e->{PROPERTIES}->{$p};
|
||||||
|
}
|
||||||
|
|
||||||
|
=item B<property_matches>
|
||||||
|
see if a pidl property matches a value
|
||||||
|
|
||||||
|
=cut
|
||||||
|
sub property_matches($$$)
|
||||||
|
{
|
||||||
|
my($e,$p,$v) = @_;
|
||||||
|
|
||||||
|
if (!defined has_property($e, $p)) {
|
||||||
|
return undef;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($e->{PROPERTIES}->{$p} =~ /$v/) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return undef;
|
||||||
|
}
|
||||||
|
|
||||||
|
=item B<is_constant>
|
||||||
|
return 1 if the string is a C constant
|
||||||
|
|
||||||
|
=cut
|
||||||
|
sub is_constant($)
|
||||||
|
{
|
||||||
|
my $s = shift;
|
||||||
|
return 1 if ($s =~ /^\d+$/);
|
||||||
|
return 1 if ($s =~ /^0x[0-9A-Fa-f]+$/);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
=item B<make_str>
|
||||||
|
return a "" quoted string, unless already quoted
|
||||||
|
|
||||||
|
=cut
|
||||||
|
sub make_str($)
|
||||||
|
{
|
||||||
|
my $str = shift;
|
||||||
|
if (substr($str, 0, 1) eq "\"") {
|
||||||
|
return $str;
|
||||||
|
}
|
||||||
|
return "\"$str\"";
|
||||||
|
}
|
||||||
|
|
||||||
|
=item B<unmake_str>
|
||||||
|
unquote a "" quoted string
|
||||||
|
|
||||||
|
=cut
|
||||||
|
sub unmake_str($)
|
||||||
|
{
|
||||||
|
my $str = shift;
|
||||||
|
|
||||||
|
$str =~ s/^\"(.*)\"$/$1/;
|
||||||
|
|
||||||
|
return $str;
|
||||||
|
}
|
||||||
|
|
||||||
|
=item B<print_uuid>
|
||||||
|
Print C representation of a UUID.
|
||||||
|
|
||||||
|
=cut
|
||||||
|
sub print_uuid($)
|
||||||
|
{
|
||||||
|
my ($uuid) = @_;
|
||||||
|
$uuid =~ s/"//g;
|
||||||
|
my ($time_low,$time_mid,$time_hi,$clock_seq,$node) = split /-/, $uuid;
|
||||||
|
return undef if not defined($node);
|
||||||
|
|
||||||
|
my @clock_seq = $clock_seq =~ /(..)/g;
|
||||||
|
my @node = $node =~ /(..)/g;
|
||||||
|
|
||||||
|
return "{0x$time_low,0x$time_mid,0x$time_hi," .
|
||||||
|
"{".join(',', map {"0x$_"} @clock_seq)."}," .
|
||||||
|
"{".join(',', map {"0x$_"} @node)."}}";
|
||||||
|
}
|
||||||
|
|
||||||
|
=item B<ParseExpr>
|
||||||
|
Interpret an IDL expression, substituting particular variables.
|
||||||
|
|
||||||
|
=cut
|
||||||
|
sub ParseExpr($$$)
|
||||||
|
{
|
||||||
|
my($expr, $varlist, $e) = @_;
|
||||||
|
|
||||||
|
my $x = new Parse::Pidl::Expr();
|
||||||
|
|
||||||
|
return $x->Run($expr, sub { my $x = shift; error($e, $x); },
|
||||||
|
# Lookup fn
|
||||||
|
sub { my $x = shift;
|
||||||
|
return($varlist->{$x}) if (defined($varlist->{$x}));
|
||||||
|
return $x;
|
||||||
|
},
|
||||||
|
undef, undef);
|
||||||
|
}
|
||||||
|
|
||||||
|
=item B<ParseExprExt>
|
||||||
|
Interpret an IDL expression, substituting particular variables. Can call
|
||||||
|
callbacks when pointers are being dereferenced or variables are being used.
|
||||||
|
|
||||||
|
=cut
|
||||||
|
sub ParseExprExt($$$$$)
|
||||||
|
{
|
||||||
|
my($expr, $varlist, $e, $deref, $use) = @_;
|
||||||
|
|
||||||
|
my $x = new Parse::Pidl::Expr();
|
||||||
|
|
||||||
|
return $x->Run($expr, sub { my $x = shift; error($e, $x); },
|
||||||
|
# Lookup fn
|
||||||
|
sub { my $x = shift;
|
||||||
|
return($varlist->{$x}) if (defined($varlist->{$x}));
|
||||||
|
return $x;
|
||||||
|
},
|
||||||
|
$deref, $use);
|
||||||
|
}
|
||||||
|
|
||||||
|
=back
|
||||||
|
|
||||||
|
=cut
|
||||||
|
|
||||||
|
1;
|
451
tools/pidl/lib/Parse/Pidl/Wireshark/Conformance.pm
Normal file
451
tools/pidl/lib/Parse/Pidl/Wireshark/Conformance.pm
Normal file
|
@ -0,0 +1,451 @@
|
||||||
|
###################################################
|
||||||
|
# parse an Wireshark conformance file
|
||||||
|
# Copyright jelmer@samba.org 2005
|
||||||
|
# released under the GNU GPL
|
||||||
|
|
||||||
|
=pod
|
||||||
|
|
||||||
|
=head1 NAME
|
||||||
|
|
||||||
|
Parse::Pidl::Wireshark::Conformance - Conformance file parser for Wireshark
|
||||||
|
|
||||||
|
=head1 DESCRIPTION
|
||||||
|
|
||||||
|
This module supports parsing Wireshark conformance files (*.cnf).
|
||||||
|
|
||||||
|
=head1 FILE FORMAT
|
||||||
|
|
||||||
|
Pidl needs additional data for Wireshark output. This data is read from
|
||||||
|
so-called conformance files. This section describes the format of these
|
||||||
|
files.
|
||||||
|
|
||||||
|
Conformance files are simple text files with a single command on each line.
|
||||||
|
Empty lines and lines starting with a '#' character are ignored.
|
||||||
|
Arguments to commands are seperated by spaces.
|
||||||
|
|
||||||
|
The following commands are currently supported:
|
||||||
|
|
||||||
|
=over 4
|
||||||
|
|
||||||
|
=item I<TYPE> name dissector ft_type base_type mask valsstring alignment
|
||||||
|
|
||||||
|
Register new data type with specified name, what dissector function to call
|
||||||
|
and what properties to give header fields for elements of this type.
|
||||||
|
|
||||||
|
=item I<NOEMIT> type
|
||||||
|
|
||||||
|
Suppress emitting a dissect_type function for the specified type
|
||||||
|
|
||||||
|
=item I<PARAM_VALUE> type param
|
||||||
|
|
||||||
|
Set parameter to specify to dissector function for given type.
|
||||||
|
|
||||||
|
=item I<HF_FIELD> hf title filter ft_type base_type valsstring mask description
|
||||||
|
|
||||||
|
Generate a custom header field with specified properties.
|
||||||
|
|
||||||
|
=item I<HF_RENAME> old_hf_name new_hf_name
|
||||||
|
|
||||||
|
Force the use of new_hf_name when the parser generator was going to
|
||||||
|
use old_hf_name.
|
||||||
|
|
||||||
|
This can be used in conjunction with HF_FIELD in order to make more than
|
||||||
|
one element use the same filter name.
|
||||||
|
|
||||||
|
=item I<ETT_FIELD> ett
|
||||||
|
|
||||||
|
Register a custom ett field
|
||||||
|
|
||||||
|
=item I<STRIP_PREFIX> prefix
|
||||||
|
|
||||||
|
Remove the specified prefix from all function names (if present).
|
||||||
|
|
||||||
|
=item I<PROTOCOL> longname shortname filtername
|
||||||
|
|
||||||
|
Change the short-, long- and filter-name for the current interface in
|
||||||
|
Wireshark.
|
||||||
|
|
||||||
|
=item I<FIELD_DESCRIPTION> field desc
|
||||||
|
|
||||||
|
Change description for the specified header field. `field' is the hf name of the field.
|
||||||
|
|
||||||
|
=item I<IMPORT> dissector code...
|
||||||
|
|
||||||
|
Code to insert when generating the specified dissector. @HF@ and
|
||||||
|
@PARAM@ will be substituted.
|
||||||
|
|
||||||
|
=item I<INCLUDE> filename
|
||||||
|
|
||||||
|
Include conformance data from the specified filename in the dissector.
|
||||||
|
|
||||||
|
=item I<TFS> hf_name "true string" "false string"
|
||||||
|
|
||||||
|
Override the text shown when a bitmap boolean value is enabled or disabled.
|
||||||
|
|
||||||
|
=item I<MANUAL> fn_name
|
||||||
|
|
||||||
|
Force pidl to not generate a particular function but allow the user
|
||||||
|
to write a function manually. This can be used to remove the function
|
||||||
|
for only one level for a particular element rather than all the functions and
|
||||||
|
ett/hf variables for a particular element as the NOEMIT command does.
|
||||||
|
|
||||||
|
=back
|
||||||
|
|
||||||
|
=head1 EXAMPLE
|
||||||
|
|
||||||
|
INFO_KEY OpenKey.Ke
|
||||||
|
|
||||||
|
=cut
|
||||||
|
|
||||||
|
package Parse::Pidl::Wireshark::Conformance;
|
||||||
|
|
||||||
|
require Exporter;
|
||||||
|
use vars qw($VERSION);
|
||||||
|
$VERSION = '0.01';
|
||||||
|
|
||||||
|
@ISA = qw(Exporter);
|
||||||
|
@EXPORT_OK = qw(ReadConformance ReadConformanceFH valid_ft_type valid_base_type);
|
||||||
|
|
||||||
|
use strict;
|
||||||
|
|
||||||
|
use Parse::Pidl qw(fatal warning error);
|
||||||
|
use Parse::Pidl::Util qw(has_property);
|
||||||
|
use Parse::Pidl::Typelist qw(addType);
|
||||||
|
|
||||||
|
sub handle_type($$$$$$$$$$)
|
||||||
|
{
|
||||||
|
my ($pos,$data,$name,$dissectorname,$ft_type,$base_type,$mask,$valsstring,$alignment) = @_;
|
||||||
|
|
||||||
|
unless(defined($alignment)) {
|
||||||
|
error($pos, "incomplete TYPE command");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
unless ($dissectorname =~ /.*dissect_.*/) {
|
||||||
|
warning($pos, "dissector name does not contain `dissect'");
|
||||||
|
}
|
||||||
|
|
||||||
|
unless(valid_ft_type($ft_type)) {
|
||||||
|
warning($pos, "invalid FT_TYPE `$ft_type'");
|
||||||
|
}
|
||||||
|
|
||||||
|
unless (valid_base_type($base_type)) {
|
||||||
|
warning($pos, "invalid BASE_TYPE `$base_type'");
|
||||||
|
}
|
||||||
|
|
||||||
|
$dissectorname =~ s/^\"(.*)\"$/$1/g;
|
||||||
|
|
||||||
|
if (not ($dissectorname =~ /;$/)) {
|
||||||
|
warning($pos, "missing semicolon");
|
||||||
|
}
|
||||||
|
|
||||||
|
$data->{types}->{$name} = {
|
||||||
|
NAME => $name,
|
||||||
|
POS => $pos,
|
||||||
|
USED => 0,
|
||||||
|
DISSECTOR_NAME => $dissectorname,
|
||||||
|
FT_TYPE => $ft_type,
|
||||||
|
BASE_TYPE => $base_type,
|
||||||
|
MASK => $mask,
|
||||||
|
VALSSTRING => $valsstring,
|
||||||
|
ALIGNMENT => $alignment
|
||||||
|
};
|
||||||
|
|
||||||
|
addType({
|
||||||
|
NAME => $name,
|
||||||
|
TYPE => "CONFORMANCE",
|
||||||
|
BASEFILE => "conformance file",
|
||||||
|
DATA => {
|
||||||
|
NAME => $name,
|
||||||
|
TYPE => "CONFORMANCE",
|
||||||
|
ALIGN => $alignment
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
sub handle_tfs($$$$$)
|
||||||
|
{
|
||||||
|
my ($pos,$data,$hf,$trues,$falses) = @_;
|
||||||
|
|
||||||
|
unless(defined($falses)) {
|
||||||
|
error($pos, "incomplete TFS command");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$data->{tfs}->{$hf} = {
|
||||||
|
TRUE_STRING => $trues,
|
||||||
|
FALSE_STRING => $falses
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
sub handle_hf_rename($$$$)
|
||||||
|
{
|
||||||
|
my ($pos,$data,$old,$new) = @_;
|
||||||
|
|
||||||
|
unless(defined($new)) {
|
||||||
|
warning($pos, "incomplete HF_RENAME command");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$data->{hf_renames}->{$old} = {
|
||||||
|
OLDNAME => $old,
|
||||||
|
NEWNAME => $new,
|
||||||
|
POS => $pos,
|
||||||
|
USED => 0
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
sub handle_param_value($$$$)
|
||||||
|
{
|
||||||
|
my ($pos,$data,$dissector_name,$value) = @_;
|
||||||
|
|
||||||
|
unless(defined($value)) {
|
||||||
|
error($pos, "incomplete PARAM_VALUE command");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$data->{dissectorparams}->{$dissector_name} = {
|
||||||
|
DISSECTOR => $dissector_name,
|
||||||
|
PARAM => $value,
|
||||||
|
POS => $pos,
|
||||||
|
USED => 0
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
sub valid_base_type($)
|
||||||
|
{
|
||||||
|
my $t = shift;
|
||||||
|
return 0 unless($t =~ /^BASE_.*/);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub valid_ft_type($)
|
||||||
|
{
|
||||||
|
my $t = shift;
|
||||||
|
return 0 unless($t =~ /^FT_.*/);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub handle_hf_field($$$$$$$$$$)
|
||||||
|
{
|
||||||
|
my ($pos,$data,$index,$name,$filter,$ft_type,$base_type,$valsstring,$mask,$blurb) = @_;
|
||||||
|
|
||||||
|
unless(defined($blurb)) {
|
||||||
|
error($pos, "incomplete HF_FIELD command");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
unless(valid_ft_type($ft_type)) {
|
||||||
|
warning($pos, "invalid FT_TYPE `$ft_type'");
|
||||||
|
}
|
||||||
|
|
||||||
|
unless(valid_base_type($base_type)) {
|
||||||
|
warning($pos, "invalid BASE_TYPE `$base_type'");
|
||||||
|
}
|
||||||
|
|
||||||
|
$data->{header_fields}->{$index} = {
|
||||||
|
INDEX => $index,
|
||||||
|
POS => $pos,
|
||||||
|
USED => 0,
|
||||||
|
NAME => $name,
|
||||||
|
FILTER => $filter,
|
||||||
|
FT_TYPE => $ft_type,
|
||||||
|
BASE_TYPE => $base_type,
|
||||||
|
VALSSTRING => $valsstring,
|
||||||
|
MASK => $mask,
|
||||||
|
BLURB => $blurb
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
sub handle_strip_prefix($$$)
|
||||||
|
{
|
||||||
|
my ($pos,$data,$x) = @_;
|
||||||
|
|
||||||
|
push (@{$data->{strip_prefixes}}, $x);
|
||||||
|
}
|
||||||
|
|
||||||
|
sub handle_noemit($$$)
|
||||||
|
{
|
||||||
|
my ($pos,$data,$type) = @_;
|
||||||
|
|
||||||
|
if (defined($type)) {
|
||||||
|
$data->{noemit}->{$type} = 1;
|
||||||
|
} else {
|
||||||
|
$data->{noemit_dissector} = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sub handle_manual($$$)
|
||||||
|
{
|
||||||
|
my ($pos,$data,$fn) = @_;
|
||||||
|
|
||||||
|
unless(defined($fn)) {
|
||||||
|
warning($pos, "incomplete MANUAL command");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$data->{manual}->{$fn} = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub handle_protocol($$$$$$)
|
||||||
|
{
|
||||||
|
my ($pos, $data, $name, $longname, $shortname, $filtername) = @_;
|
||||||
|
|
||||||
|
$data->{protocols}->{$name} = {
|
||||||
|
LONGNAME => $longname,
|
||||||
|
SHORTNAME => $shortname,
|
||||||
|
FILTERNAME => $filtername
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
sub handle_fielddescription($$$$)
|
||||||
|
{
|
||||||
|
my ($pos,$data,$field,$desc) = @_;
|
||||||
|
|
||||||
|
unless(defined($desc)) {
|
||||||
|
warning($pos, "incomplete FIELD_DESCRIPTION command");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$data->{fielddescription}->{$field} = {
|
||||||
|
DESCRIPTION => $desc,
|
||||||
|
POS => $pos,
|
||||||
|
USED => 0
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
sub handle_import
|
||||||
|
{
|
||||||
|
my $pos = shift @_;
|
||||||
|
my $data = shift @_;
|
||||||
|
my $dissectorname = shift @_;
|
||||||
|
|
||||||
|
unless(defined($dissectorname)) {
|
||||||
|
error($pos, "no dissectorname specified");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$data->{imports}->{$dissectorname} = {
|
||||||
|
NAME => $dissectorname,
|
||||||
|
DATA => join(' ', @_),
|
||||||
|
USED => 0,
|
||||||
|
POS => $pos
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
sub handle_ett_field
|
||||||
|
{
|
||||||
|
my $pos = shift @_;
|
||||||
|
my $data = shift @_;
|
||||||
|
my $ett = shift @_;
|
||||||
|
|
||||||
|
unless(defined($ett)) {
|
||||||
|
error($pos, "incomplete ETT_FIELD command");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
push (@{$data->{ett}}, $ett);
|
||||||
|
}
|
||||||
|
|
||||||
|
sub handle_include
|
||||||
|
{
|
||||||
|
my $pos = shift @_;
|
||||||
|
my $data = shift @_;
|
||||||
|
my $fn = shift @_;
|
||||||
|
|
||||||
|
unless(defined($fn)) {
|
||||||
|
error($pos, "incomplete INCLUDE command");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ReadConformance($fn, $data);
|
||||||
|
}
|
||||||
|
|
||||||
|
my %field_handlers = (
|
||||||
|
TYPE => \&handle_type,
|
||||||
|
NOEMIT => \&handle_noemit,
|
||||||
|
MANUAL => \&handle_manual,
|
||||||
|
PARAM_VALUE => \&handle_param_value,
|
||||||
|
HF_FIELD => \&handle_hf_field,
|
||||||
|
HF_RENAME => \&handle_hf_rename,
|
||||||
|
ETT_FIELD => \&handle_ett_field,
|
||||||
|
TFS => \&handle_tfs,
|
||||||
|
STRIP_PREFIX => \&handle_strip_prefix,
|
||||||
|
PROTOCOL => \&handle_protocol,
|
||||||
|
FIELD_DESCRIPTION => \&handle_fielddescription,
|
||||||
|
IMPORT => \&handle_import,
|
||||||
|
INCLUDE => \&handle_include
|
||||||
|
);
|
||||||
|
|
||||||
|
sub ReadConformance($$)
|
||||||
|
{
|
||||||
|
my ($f,$data) = @_;
|
||||||
|
my $ret;
|
||||||
|
|
||||||
|
open(IN,"<$f") or return undef;
|
||||||
|
|
||||||
|
$ret = ReadConformanceFH(*IN, $data, $f);
|
||||||
|
|
||||||
|
close(IN);
|
||||||
|
|
||||||
|
return $ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub ReadConformanceFH($$$)
|
||||||
|
{
|
||||||
|
my ($fh,$data,$f) = @_;
|
||||||
|
|
||||||
|
my $incodeblock = 0;
|
||||||
|
|
||||||
|
my $ln = 0;
|
||||||
|
|
||||||
|
foreach (<$fh>) {
|
||||||
|
$ln++;
|
||||||
|
next if (/^#.*$/);
|
||||||
|
next if (/^$/);
|
||||||
|
|
||||||
|
s/[\r\n]//g;
|
||||||
|
|
||||||
|
if ($_ eq "CODE START") {
|
||||||
|
$incodeblock = 1;
|
||||||
|
next;
|
||||||
|
} elsif ($incodeblock and $_ eq "CODE END") {
|
||||||
|
$incodeblock = 0;
|
||||||
|
next;
|
||||||
|
} elsif ($incodeblock) {
|
||||||
|
if (exists $data->{override}) {
|
||||||
|
$data->{override}.="$_\n";
|
||||||
|
} else {
|
||||||
|
$data->{override} = "$_\n";
|
||||||
|
}
|
||||||
|
next;
|
||||||
|
}
|
||||||
|
|
||||||
|
my @fields = /([^ "]+|"[^"]+")/g;
|
||||||
|
|
||||||
|
my $cmd = $fields[0];
|
||||||
|
|
||||||
|
shift @fields;
|
||||||
|
|
||||||
|
my $pos = { FILE => $f, LINE => $ln };
|
||||||
|
|
||||||
|
next unless(defined($cmd));
|
||||||
|
|
||||||
|
if (not defined($field_handlers{$cmd})) {
|
||||||
|
warning($pos, "Unknown command `$cmd'");
|
||||||
|
next;
|
||||||
|
}
|
||||||
|
|
||||||
|
$field_handlers{$cmd}($pos, $data, @fields);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($incodeblock) {
|
||||||
|
warning({ FILE => $f, LINE => $ln },
|
||||||
|
"Expecting CODE END");
|
||||||
|
return undef;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
1;
|
1263
tools/pidl/lib/Parse/Pidl/Wireshark/NDR.pm
Normal file
1263
tools/pidl/lib/Parse/Pidl/Wireshark/NDR.pm
Normal file
File diff suppressed because it is too large
Load Diff
471
tools/pidl/lib/Parse/Yapp/Driver.pm
Normal file
471
tools/pidl/lib/Parse/Yapp/Driver.pm
Normal file
|
@ -0,0 +1,471 @@
|
||||||
|
#
|
||||||
|
# Module Parse::Yapp::Driver
|
||||||
|
#
|
||||||
|
# This module is part of the Parse::Yapp package available on your
|
||||||
|
# nearest CPAN
|
||||||
|
#
|
||||||
|
# Any use of this module in a standalone parser make the included
|
||||||
|
# text under the same copyright as the Parse::Yapp module itself.
|
||||||
|
#
|
||||||
|
# This notice should remain unchanged.
|
||||||
|
#
|
||||||
|
# (c) Copyright 1998-2001 Francois Desarmenien, all rights reserved.
|
||||||
|
# (see the pod text in Parse::Yapp module for use and distribution rights)
|
||||||
|
#
|
||||||
|
|
||||||
|
package Parse::Yapp::Driver;
|
||||||
|
|
||||||
|
require 5.004;
|
||||||
|
|
||||||
|
use strict;
|
||||||
|
|
||||||
|
use vars qw ( $VERSION $COMPATIBLE $FILENAME );
|
||||||
|
|
||||||
|
$VERSION = '1.05';
|
||||||
|
$COMPATIBLE = '0.07';
|
||||||
|
$FILENAME=__FILE__;
|
||||||
|
|
||||||
|
use Carp;
|
||||||
|
|
||||||
|
#Known parameters, all starting with YY (leading YY will be discarded)
|
||||||
|
my(%params)=(YYLEX => 'CODE', 'YYERROR' => 'CODE', YYVERSION => '',
|
||||||
|
YYRULES => 'ARRAY', YYSTATES => 'ARRAY', YYDEBUG => '');
|
||||||
|
#Mandatory parameters
|
||||||
|
my(@params)=('LEX','RULES','STATES');
|
||||||
|
|
||||||
|
sub new {
|
||||||
|
my($class)=shift;
|
||||||
|
my($errst,$nberr,$token,$value,$check,$dotpos);
|
||||||
|
my($self)={ ERROR => \&_Error,
|
||||||
|
ERRST => \$errst,
|
||||||
|
NBERR => \$nberr,
|
||||||
|
TOKEN => \$token,
|
||||||
|
VALUE => \$value,
|
||||||
|
DOTPOS => \$dotpos,
|
||||||
|
STACK => [],
|
||||||
|
DEBUG => 0,
|
||||||
|
CHECK => \$check };
|
||||||
|
|
||||||
|
_CheckParams( [], \%params, \@_, $self );
|
||||||
|
|
||||||
|
exists($$self{VERSION})
|
||||||
|
and $$self{VERSION} < $COMPATIBLE
|
||||||
|
and croak "Yapp driver version $VERSION ".
|
||||||
|
"incompatible with version $$self{VERSION}:\n".
|
||||||
|
"Please recompile parser module.";
|
||||||
|
|
||||||
|
ref($class)
|
||||||
|
and $class=ref($class);
|
||||||
|
|
||||||
|
bless($self,$class);
|
||||||
|
}
|
||||||
|
|
||||||
|
sub YYParse {
|
||||||
|
my($self)=shift;
|
||||||
|
my($retval);
|
||||||
|
|
||||||
|
_CheckParams( \@params, \%params, \@_, $self );
|
||||||
|
|
||||||
|
if($$self{DEBUG}) {
|
||||||
|
_DBLoad();
|
||||||
|
$retval = eval '$self->_DBParse()';#Do not create stab entry on compile
|
||||||
|
$@ and die $@;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$retval = $self->_Parse();
|
||||||
|
}
|
||||||
|
$retval
|
||||||
|
}
|
||||||
|
|
||||||
|
sub YYData {
|
||||||
|
my($self)=shift;
|
||||||
|
|
||||||
|
exists($$self{USER})
|
||||||
|
or $$self{USER}={};
|
||||||
|
|
||||||
|
$$self{USER};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
sub YYErrok {
|
||||||
|
my($self)=shift;
|
||||||
|
|
||||||
|
${$$self{ERRST}}=0;
|
||||||
|
undef;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub YYNberr {
|
||||||
|
my($self)=shift;
|
||||||
|
|
||||||
|
${$$self{NBERR}};
|
||||||
|
}
|
||||||
|
|
||||||
|
sub YYRecovering {
|
||||||
|
my($self)=shift;
|
||||||
|
|
||||||
|
${$$self{ERRST}} != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub YYAbort {
|
||||||
|
my($self)=shift;
|
||||||
|
|
||||||
|
${$$self{CHECK}}='ABORT';
|
||||||
|
undef;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub YYAccept {
|
||||||
|
my($self)=shift;
|
||||||
|
|
||||||
|
${$$self{CHECK}}='ACCEPT';
|
||||||
|
undef;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub YYError {
|
||||||
|
my($self)=shift;
|
||||||
|
|
||||||
|
${$$self{CHECK}}='ERROR';
|
||||||
|
undef;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub YYSemval {
|
||||||
|
my($self)=shift;
|
||||||
|
my($index)= $_[0] - ${$$self{DOTPOS}} - 1;
|
||||||
|
|
||||||
|
$index < 0
|
||||||
|
and -$index <= @{$$self{STACK}}
|
||||||
|
and return $$self{STACK}[$index][1];
|
||||||
|
|
||||||
|
undef; #Invalid index
|
||||||
|
}
|
||||||
|
|
||||||
|
sub YYCurtok {
|
||||||
|
my($self)=shift;
|
||||||
|
|
||||||
|
@_
|
||||||
|
and ${$$self{TOKEN}}=$_[0];
|
||||||
|
${$$self{TOKEN}};
|
||||||
|
}
|
||||||
|
|
||||||
|
sub YYCurval {
|
||||||
|
my($self)=shift;
|
||||||
|
|
||||||
|
@_
|
||||||
|
and ${$$self{VALUE}}=$_[0];
|
||||||
|
${$$self{VALUE}};
|
||||||
|
}
|
||||||
|
|
||||||
|
sub YYExpect {
|
||||||
|
my($self)=shift;
|
||||||
|
|
||||||
|
keys %{$self->{STATES}[$self->{STACK}[-1][0]]{ACTIONS}}
|
||||||
|
}
|
||||||
|
|
||||||
|
sub YYLexer {
|
||||||
|
my($self)=shift;
|
||||||
|
|
||||||
|
$$self{LEX};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#################
|
||||||
|
# Private stuff #
|
||||||
|
#################
|
||||||
|
|
||||||
|
|
||||||
|
sub _CheckParams {
|
||||||
|
my($mandatory,$checklist,$inarray,$outhash)=@_;
|
||||||
|
my($prm,$value);
|
||||||
|
my($prmlst)={};
|
||||||
|
|
||||||
|
while(($prm,$value)=splice(@$inarray,0,2)) {
|
||||||
|
$prm=uc($prm);
|
||||||
|
exists($$checklist{$prm})
|
||||||
|
or croak("Unknow parameter '$prm'");
|
||||||
|
ref($value) eq $$checklist{$prm}
|
||||||
|
or croak("Invalid value for parameter '$prm'");
|
||||||
|
$prm=unpack('@2A*',$prm);
|
||||||
|
$$outhash{$prm}=$value;
|
||||||
|
}
|
||||||
|
for (@$mandatory) {
|
||||||
|
exists($$outhash{$_})
|
||||||
|
or croak("Missing mandatory parameter '".lc($_)."'");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sub _Error {
|
||||||
|
print "Parse error.\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
sub _DBLoad {
|
||||||
|
{
|
||||||
|
no strict 'refs';
|
||||||
|
|
||||||
|
exists(${__PACKAGE__.'::'}{_DBParse})#Already loaded ?
|
||||||
|
and return;
|
||||||
|
}
|
||||||
|
my($fname)=__FILE__;
|
||||||
|
my(@drv);
|
||||||
|
open(DRV,"<$fname") or die "Report this as a BUG: Cannot open $fname";
|
||||||
|
while(<DRV>) {
|
||||||
|
/^\s*sub\s+_Parse\s*{\s*$/ .. /^\s*}\s*#\s*_Parse\s*$/
|
||||||
|
and do {
|
||||||
|
s/^#DBG>//;
|
||||||
|
push(@drv,$_);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
close(DRV);
|
||||||
|
|
||||||
|
$drv[0]=~s/_P/_DBP/;
|
||||||
|
eval join('',@drv);
|
||||||
|
}
|
||||||
|
|
||||||
|
#Note that for loading debugging version of the driver,
|
||||||
|
#this file will be parsed from 'sub _Parse' up to '}#_Parse' inclusive.
|
||||||
|
#So, DO NOT remove comment at end of sub !!!
|
||||||
|
sub _Parse {
|
||||||
|
my($self)=shift;
|
||||||
|
|
||||||
|
my($rules,$states,$lex,$error)
|
||||||
|
= @$self{ 'RULES', 'STATES', 'LEX', 'ERROR' };
|
||||||
|
my($errstatus,$nberror,$token,$value,$stack,$check,$dotpos)
|
||||||
|
= @$self{ 'ERRST', 'NBERR', 'TOKEN', 'VALUE', 'STACK', 'CHECK', 'DOTPOS' };
|
||||||
|
|
||||||
|
#DBG> my($debug)=$$self{DEBUG};
|
||||||
|
#DBG> my($dbgerror)=0;
|
||||||
|
|
||||||
|
#DBG> my($ShowCurToken) = sub {
|
||||||
|
#DBG> my($tok)='>';
|
||||||
|
#DBG> for (split('',$$token)) {
|
||||||
|
#DBG> $tok.= (ord($_) < 32 or ord($_) > 126)
|
||||||
|
#DBG> ? sprintf('<%02X>',ord($_))
|
||||||
|
#DBG> : $_;
|
||||||
|
#DBG> }
|
||||||
|
#DBG> $tok.='<';
|
||||||
|
#DBG> };
|
||||||
|
|
||||||
|
$$errstatus=0;
|
||||||
|
$$nberror=0;
|
||||||
|
($$token,$$value)=(undef,undef);
|
||||||
|
@$stack=( [ 0, undef ] );
|
||||||
|
$$check='';
|
||||||
|
|
||||||
|
while(1) {
|
||||||
|
my($actions,$act,$stateno);
|
||||||
|
|
||||||
|
$stateno=$$stack[-1][0];
|
||||||
|
$actions=$$states[$stateno];
|
||||||
|
|
||||||
|
#DBG> print STDERR ('-' x 40),"\n";
|
||||||
|
#DBG> $debug & 0x2
|
||||||
|
#DBG> and print STDERR "In state $stateno:\n";
|
||||||
|
#DBG> $debug & 0x08
|
||||||
|
#DBG> and print STDERR "Stack:[".
|
||||||
|
#DBG> join(',',map { $$_[0] } @$stack).
|
||||||
|
#DBG> "]\n";
|
||||||
|
|
||||||
|
|
||||||
|
if (exists($$actions{ACTIONS})) {
|
||||||
|
|
||||||
|
defined($$token)
|
||||||
|
or do {
|
||||||
|
($$token,$$value)=&$lex($self);
|
||||||
|
#DBG> $debug & 0x01
|
||||||
|
#DBG> and print STDERR "Need token. Got ".&$ShowCurToken."\n";
|
||||||
|
};
|
||||||
|
|
||||||
|
$act= exists($$actions{ACTIONS}{$$token})
|
||||||
|
? $$actions{ACTIONS}{$$token}
|
||||||
|
: exists($$actions{DEFAULT})
|
||||||
|
? $$actions{DEFAULT}
|
||||||
|
: undef;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$act=$$actions{DEFAULT};
|
||||||
|
#DBG> $debug & 0x01
|
||||||
|
#DBG> and print STDERR "Don't need token.\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
defined($act)
|
||||||
|
and do {
|
||||||
|
|
||||||
|
$act > 0
|
||||||
|
and do { #shift
|
||||||
|
|
||||||
|
#DBG> $debug & 0x04
|
||||||
|
#DBG> and print STDERR "Shift and go to state $act.\n";
|
||||||
|
|
||||||
|
$$errstatus
|
||||||
|
and do {
|
||||||
|
--$$errstatus;
|
||||||
|
|
||||||
|
#DBG> $debug & 0x10
|
||||||
|
#DBG> and $dbgerror
|
||||||
|
#DBG> and $$errstatus == 0
|
||||||
|
#DBG> and do {
|
||||||
|
#DBG> print STDERR "**End of Error recovery.\n";
|
||||||
|
#DBG> $dbgerror=0;
|
||||||
|
#DBG> };
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
push(@$stack,[ $act, $$value ]);
|
||||||
|
|
||||||
|
$$token ne '' #Don't eat the eof
|
||||||
|
and $$token=$$value=undef;
|
||||||
|
next;
|
||||||
|
};
|
||||||
|
|
||||||
|
#reduce
|
||||||
|
my($lhs,$len,$code,@sempar,$semval);
|
||||||
|
($lhs,$len,$code)=@{$$rules[-$act]};
|
||||||
|
|
||||||
|
#DBG> $debug & 0x04
|
||||||
|
#DBG> and $act
|
||||||
|
#DBG> and print STDERR "Reduce using rule ".-$act." ($lhs,$len): ";
|
||||||
|
|
||||||
|
$act
|
||||||
|
or $self->YYAccept();
|
||||||
|
|
||||||
|
$$dotpos=$len;
|
||||||
|
|
||||||
|
unpack('A1',$lhs) eq '@' #In line rule
|
||||||
|
and do {
|
||||||
|
$lhs =~ /^\@[0-9]+\-([0-9]+)$/
|
||||||
|
or die "In line rule name '$lhs' ill formed: ".
|
||||||
|
"report it as a BUG.\n";
|
||||||
|
$$dotpos = $1;
|
||||||
|
};
|
||||||
|
|
||||||
|
@sempar = $$dotpos
|
||||||
|
? map { $$_[1] } @$stack[ -$$dotpos .. -1 ]
|
||||||
|
: ();
|
||||||
|
|
||||||
|
$semval = $code ? &$code( $self, @sempar )
|
||||||
|
: @sempar ? $sempar[0] : undef;
|
||||||
|
|
||||||
|
splice(@$stack,-$len,$len);
|
||||||
|
|
||||||
|
$$check eq 'ACCEPT'
|
||||||
|
and do {
|
||||||
|
|
||||||
|
#DBG> $debug & 0x04
|
||||||
|
#DBG> and print STDERR "Accept.\n";
|
||||||
|
|
||||||
|
return($semval);
|
||||||
|
};
|
||||||
|
|
||||||
|
$$check eq 'ABORT'
|
||||||
|
and do {
|
||||||
|
|
||||||
|
#DBG> $debug & 0x04
|
||||||
|
#DBG> and print STDERR "Abort.\n";
|
||||||
|
|
||||||
|
return(undef);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#DBG> $debug & 0x04
|
||||||
|
#DBG> and print STDERR "Back to state $$stack[-1][0], then ";
|
||||||
|
|
||||||
|
$$check eq 'ERROR'
|
||||||
|
or do {
|
||||||
|
#DBG> $debug & 0x04
|
||||||
|
#DBG> and print STDERR
|
||||||
|
#DBG> "go to state $$states[$$stack[-1][0]]{GOTOS}{$lhs}.\n";
|
||||||
|
|
||||||
|
#DBG> $debug & 0x10
|
||||||
|
#DBG> and $dbgerror
|
||||||
|
#DBG> and $$errstatus == 0
|
||||||
|
#DBG> and do {
|
||||||
|
#DBG> print STDERR "**End of Error recovery.\n";
|
||||||
|
#DBG> $dbgerror=0;
|
||||||
|
#DBG> };
|
||||||
|
|
||||||
|
push(@$stack,
|
||||||
|
[ $$states[$$stack[-1][0]]{GOTOS}{$lhs}, $semval ]);
|
||||||
|
$$check='';
|
||||||
|
next;
|
||||||
|
};
|
||||||
|
|
||||||
|
#DBG> $debug & 0x04
|
||||||
|
#DBG> and print STDERR "Forced Error recovery.\n";
|
||||||
|
|
||||||
|
$$check='';
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#Error
|
||||||
|
$$errstatus
|
||||||
|
or do {
|
||||||
|
|
||||||
|
$$errstatus = 1;
|
||||||
|
&$error($self);
|
||||||
|
$$errstatus # if 0, then YYErrok has been called
|
||||||
|
or next; # so continue parsing
|
||||||
|
|
||||||
|
#DBG> $debug & 0x10
|
||||||
|
#DBG> and do {
|
||||||
|
#DBG> print STDERR "**Entering Error recovery.\n";
|
||||||
|
#DBG> ++$dbgerror;
|
||||||
|
#DBG> };
|
||||||
|
|
||||||
|
++$$nberror;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
$$errstatus == 3 #The next token is not valid: discard it
|
||||||
|
and do {
|
||||||
|
$$token eq '' # End of input: no hope
|
||||||
|
and do {
|
||||||
|
#DBG> $debug & 0x10
|
||||||
|
#DBG> and print STDERR "**At eof: aborting.\n";
|
||||||
|
return(undef);
|
||||||
|
};
|
||||||
|
|
||||||
|
#DBG> $debug & 0x10
|
||||||
|
#DBG> and print STDERR "**Dicard invalid token ".&$ShowCurToken.".\n";
|
||||||
|
|
||||||
|
$$token=$$value=undef;
|
||||||
|
};
|
||||||
|
|
||||||
|
$$errstatus=3;
|
||||||
|
|
||||||
|
while( @$stack
|
||||||
|
and ( not exists($$states[$$stack[-1][0]]{ACTIONS})
|
||||||
|
or not exists($$states[$$stack[-1][0]]{ACTIONS}{error})
|
||||||
|
or $$states[$$stack[-1][0]]{ACTIONS}{error} <= 0)) {
|
||||||
|
|
||||||
|
#DBG> $debug & 0x10
|
||||||
|
#DBG> and print STDERR "**Pop state $$stack[-1][0].\n";
|
||||||
|
|
||||||
|
pop(@$stack);
|
||||||
|
}
|
||||||
|
|
||||||
|
@$stack
|
||||||
|
or do {
|
||||||
|
|
||||||
|
#DBG> $debug & 0x10
|
||||||
|
#DBG> and print STDERR "**No state left on stack: aborting.\n";
|
||||||
|
|
||||||
|
return(undef);
|
||||||
|
};
|
||||||
|
|
||||||
|
#shift the error token
|
||||||
|
|
||||||
|
#DBG> $debug & 0x10
|
||||||
|
#DBG> and print STDERR "**Shift \$error token and go to state ".
|
||||||
|
#DBG> $$states[$$stack[-1][0]]{ACTIONS}{error}.
|
||||||
|
#DBG> ".\n";
|
||||||
|
|
||||||
|
push(@$stack, [ $$states[$$stack[-1][0]]{ACTIONS}{error}, undef ]);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#never reached
|
||||||
|
croak("Error in driver logic. Please, report it as a BUG");
|
||||||
|
|
||||||
|
}#_Parse
|
||||||
|
#DO NOT remove comment
|
||||||
|
|
||||||
|
1;
|
||||||
|
|
4
tools/pidl/lib/wscript_build
Normal file
4
tools/pidl/lib/wscript_build
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
# install the pidl modules
|
||||||
|
bld.INSTALL_WILDCARD('${DATAROOTDIR}/perl5', '**/*.pm', flat=False)
|
839
tools/pidl/pidl
Executable file
839
tools/pidl/pidl
Executable file
|
@ -0,0 +1,839 @@
|
||||||
|
#!/usr/bin/env perl
|
||||||
|
|
||||||
|
###################################################
|
||||||
|
# package to parse IDL files and generate code for
|
||||||
|
# rpc functions in Samba
|
||||||
|
# Copyright tridge@samba.org 2000-2003
|
||||||
|
# Copyright jelmer@samba.org 2005-2007
|
||||||
|
# released under the GNU GPL
|
||||||
|
# Modifications for COMROGUE - Copyright erbo@erbosoft.com 2013
|
||||||
|
|
||||||
|
=pod
|
||||||
|
|
||||||
|
=head1 NAME
|
||||||
|
|
||||||
|
pidl - An IDL compiler written in Perl
|
||||||
|
|
||||||
|
=head1 SYNOPSIS
|
||||||
|
|
||||||
|
pidl --help
|
||||||
|
|
||||||
|
pidl [--outputdir[=OUTNAME]] [--includedir DIR...] [--parse-idl-tree] [--dump-idl-tree] [--dump-ndr-tree] [--header[=OUTPUT]] [--python[=OUTPUT]] [--ndr-parser[=OUTPUT]] [--client] [--server] [--warn-compat] [--quiet] [--verbose] [--template] [--ws-parser[=OUTPUT]] [--diff] [--dump-idl] [--tdr-parser[=OUTPUT]] [--samba3-ndr-client[=OUTPUT]] [--samba3-ndr-server[=OUTPUT]] [--typelib=[OUTPUT]] [--comrogue-header=[OUTPUT]] [<idlfile>.idl]...
|
||||||
|
|
||||||
|
=head1 DESCRIPTION
|
||||||
|
|
||||||
|
pidl is an IDL compiler written in Perl that aims to be somewhat
|
||||||
|
compatible with the midl compiler. IDL is short for
|
||||||
|
"Interface Definition Language".
|
||||||
|
|
||||||
|
pidl can generate stubs for DCE/RPC server code, DCE/RPC
|
||||||
|
client code and Wireshark dissectors for DCE/RPC traffic.
|
||||||
|
|
||||||
|
IDL compilers like pidl take a description
|
||||||
|
of an interface as their input and use it to generate C
|
||||||
|
(though support for other languages may be added later) code that
|
||||||
|
can use these interfaces, pretty print data sent
|
||||||
|
using these interfaces, or even generate Wireshark
|
||||||
|
dissectors that can parse data sent over the
|
||||||
|
wire by these interfaces.
|
||||||
|
|
||||||
|
pidl takes IDL files in the same format as is used by midl,
|
||||||
|
converts it to a .pidl file (which contains pidl's internal representation of the interface) and can then generate whatever output you need.
|
||||||
|
.pidl files should be used for debugging purposes only. Write your
|
||||||
|
interface definitions in .idl format.
|
||||||
|
|
||||||
|
The goal of pidl is to implement a IDL compiler that can be used
|
||||||
|
while developing the RPC subsystem in Samba (for
|
||||||
|
both marshalling/unmarshalling and debugging purposes).
|
||||||
|
|
||||||
|
For COMROGUE, pidl generates the header files for interfaces.
|
||||||
|
|
||||||
|
=head1 OPTIONS
|
||||||
|
|
||||||
|
=over 4
|
||||||
|
|
||||||
|
=item I<--help>
|
||||||
|
|
||||||
|
Show list of available options.
|
||||||
|
|
||||||
|
=item I<--version>
|
||||||
|
|
||||||
|
Show pidl version
|
||||||
|
|
||||||
|
=item I<--outputdir OUTNAME>
|
||||||
|
|
||||||
|
Write output files to the specified directory. Defaults to the current
|
||||||
|
directory.
|
||||||
|
|
||||||
|
=item I<--includedir DIR>
|
||||||
|
|
||||||
|
Add DIR to the search path used by the preprocessor. This option can be
|
||||||
|
specified multiple times.
|
||||||
|
|
||||||
|
=item I<--parse-idl-tree>
|
||||||
|
|
||||||
|
Read internal tree structure from input files rather
|
||||||
|
than assuming they contain IDL.
|
||||||
|
|
||||||
|
=item I<--dump-idl>
|
||||||
|
|
||||||
|
Generate a new IDL file. File will be named OUTNAME.idl.
|
||||||
|
|
||||||
|
=item I<--header>
|
||||||
|
|
||||||
|
Generate a C header file for the specified interface. Filename defaults to OUTNAME.h.
|
||||||
|
|
||||||
|
=item I<--ndr-parser>
|
||||||
|
|
||||||
|
Generate a C file and C header containing NDR parsers. The filename for
|
||||||
|
the parser defaults to ndr_OUTNAME.c. The header filename will be the
|
||||||
|
parser filename with the extension changed from .c to .h.
|
||||||
|
|
||||||
|
=item I<--tdr-parser>
|
||||||
|
|
||||||
|
Generate a C file and C header containing TDR parsers. The filename for
|
||||||
|
the parser defaults to tdr_OUTNAME.c. The header filename will be the
|
||||||
|
parser filename with the extension changed from .c to .h.
|
||||||
|
|
||||||
|
=item I<--typelib>
|
||||||
|
|
||||||
|
Write type information to the specified file.
|
||||||
|
|
||||||
|
=item I<--server>
|
||||||
|
|
||||||
|
Generate boilerplate for the RPC server that implements
|
||||||
|
the interface. Filename defaults to ndr_OUTNAME_s.c.
|
||||||
|
|
||||||
|
=item I<--template>
|
||||||
|
|
||||||
|
Generate stubs for a RPC server that implements the interface. Output will
|
||||||
|
be written to stdout.
|
||||||
|
|
||||||
|
=item I<--ws-parser>
|
||||||
|
|
||||||
|
Generate an Wireshark dissector (in C) and header file. The dissector filename
|
||||||
|
defaults to packet-dcerpc-OUTNAME.c while the header filename defaults to
|
||||||
|
packet-dcerpc-OUTNAME.h.
|
||||||
|
|
||||||
|
Pidl will read additional data from an Wireshark conformance file if present.
|
||||||
|
Such a file should have the same location as the IDL file but with the
|
||||||
|
extension I<cnf> rather than I<idl>. See L<Parse::Pidl::Wireshark::Conformance>
|
||||||
|
for details on the format of this file.
|
||||||
|
|
||||||
|
=item I<--diff>
|
||||||
|
|
||||||
|
Parse an IDL file, generate a new IDL file based on the internal data
|
||||||
|
structures and see if there are any differences with the original IDL file.
|
||||||
|
Useful for debugging pidl.
|
||||||
|
|
||||||
|
=item I<--dump-idl-tree>
|
||||||
|
|
||||||
|
Tell pidl to dump the internal tree representation of an IDL
|
||||||
|
file the to disk. Useful for debugging pidl.
|
||||||
|
|
||||||
|
=item I<--dump-ndr-tree>
|
||||||
|
|
||||||
|
Tell pidl to dump the internal NDR information tree it generated
|
||||||
|
from the IDL file to disk. Useful for debugging pidl.
|
||||||
|
|
||||||
|
=item I<--samba3-ndr-client>
|
||||||
|
|
||||||
|
Generate client calls for Samba3, to be placed in rpc_client/. Instead of
|
||||||
|
calling out to the code in Samba3's rpc_parse/, this will call out to
|
||||||
|
Samba4's NDR code instead.
|
||||||
|
|
||||||
|
=item I<--samba3-ndr-server>
|
||||||
|
|
||||||
|
Generate server calls for Samba3, to be placed in rpc_server/. Instead of
|
||||||
|
calling out to the code in Samba3's rpc_parse/, this will call out to
|
||||||
|
Samba4's NDR code instead.
|
||||||
|
|
||||||
|
=item I<--comrogue-header>
|
||||||
|
|
||||||
|
Generate interface header files for COMROGUE. Filename defaults to
|
||||||
|
OUTNAME.h.
|
||||||
|
|
||||||
|
=back
|
||||||
|
|
||||||
|
=head1 IDL SYNTAX
|
||||||
|
|
||||||
|
IDL files are always preprocessed using the C preprocessor.
|
||||||
|
|
||||||
|
Pretty much everything in an interface (the interface itself, functions,
|
||||||
|
parameters) can have attributes (or properties whatever name you give them).
|
||||||
|
Attributes always prepend the element they apply to and are surrounded
|
||||||
|
by square brackets ([]). Multiple attributes are separated by comma's;
|
||||||
|
arguments to attributes are specified between parentheses.
|
||||||
|
|
||||||
|
See the section COMPATIBILITY for the list of attributes that
|
||||||
|
pidl supports.
|
||||||
|
|
||||||
|
C-style comments can be used.
|
||||||
|
|
||||||
|
=head2 CONFORMANT ARRAYS
|
||||||
|
|
||||||
|
A conformant array is one with that ends in [*] or []. The strange
|
||||||
|
things about conformant arrays are that they can only appear as the last
|
||||||
|
element of a structure (unless there is a pointer to the conformant array,
|
||||||
|
of course) and the array size appears before the structure itself on the wire.
|
||||||
|
|
||||||
|
So, in this example:
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
long abc;
|
||||||
|
long count;
|
||||||
|
long foo;
|
||||||
|
[size_is(count)] long s[*];
|
||||||
|
} Struct1;
|
||||||
|
|
||||||
|
it appears like this:
|
||||||
|
|
||||||
|
[size_is] [abc] [count] [foo] [s...]
|
||||||
|
|
||||||
|
the first [size_is] field is the allocation size of the array, and
|
||||||
|
occurs before the array elements and even before the structure
|
||||||
|
alignment.
|
||||||
|
|
||||||
|
Note that size_is() can refer to a constant, but that doesn't change
|
||||||
|
the wire representation. It does not make the array a fixed array.
|
||||||
|
|
||||||
|
midl.exe would write the above array as the following C header:
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
long abc;
|
||||||
|
long count;
|
||||||
|
long foo;
|
||||||
|
long s[1];
|
||||||
|
} Struct1;
|
||||||
|
|
||||||
|
pidl takes a different approach, and writes it like this:
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
long abc;
|
||||||
|
long count;
|
||||||
|
long foo;
|
||||||
|
long *s;
|
||||||
|
} Struct1;
|
||||||
|
|
||||||
|
=head2 VARYING ARRAYS
|
||||||
|
|
||||||
|
A varying array looks like this:
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
long abc;
|
||||||
|
long count;
|
||||||
|
long foo;
|
||||||
|
[size_is(count)] long *s;
|
||||||
|
} Struct1;
|
||||||
|
|
||||||
|
This will look like this on the wire:
|
||||||
|
|
||||||
|
[abc] [count] [foo] [PTR_s] [count] [s...]
|
||||||
|
|
||||||
|
=head2 FIXED ARRAYS
|
||||||
|
|
||||||
|
A fixed array looks like this:
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
long s[10];
|
||||||
|
} Struct1;
|
||||||
|
|
||||||
|
The NDR representation looks just like 10 separate long
|
||||||
|
declarations. The array size is not encoded on the wire.
|
||||||
|
|
||||||
|
pidl also supports "inline" arrays, which are not part of the IDL/NDR
|
||||||
|
standard. These are declared like this:
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint32 foo;
|
||||||
|
uint32 count;
|
||||||
|
uint32 bar;
|
||||||
|
long s[count];
|
||||||
|
} Struct1;
|
||||||
|
|
||||||
|
This appears like this:
|
||||||
|
|
||||||
|
[foo] [count] [bar] [s...]
|
||||||
|
|
||||||
|
Fixed arrays are an extension added to support some of the strange
|
||||||
|
embedded structures in security descriptors and spoolss.
|
||||||
|
|
||||||
|
This section is by no means complete. See the OpenGroup and MSDN
|
||||||
|
documentation for additional information.
|
||||||
|
|
||||||
|
=head1 COMPATIBILITY WITH MIDL
|
||||||
|
|
||||||
|
=head2 Missing features in pidl
|
||||||
|
|
||||||
|
The following MIDL features are not (yet) implemented in pidl
|
||||||
|
or are implemented with an incompatible interface:
|
||||||
|
|
||||||
|
=over
|
||||||
|
|
||||||
|
=item *
|
||||||
|
|
||||||
|
Asynchronous communication
|
||||||
|
|
||||||
|
=item *
|
||||||
|
|
||||||
|
Typelibs (.tlb files)
|
||||||
|
|
||||||
|
=item *
|
||||||
|
|
||||||
|
Datagram support (ncadg_*)
|
||||||
|
|
||||||
|
=back
|
||||||
|
|
||||||
|
=head2 Supported attributes and statements
|
||||||
|
|
||||||
|
in, out, ref, length_is, switch_is, size_is, uuid, case, default, string,
|
||||||
|
unique, ptr, pointer_default, v1_enum, object, helpstring, range, local,
|
||||||
|
call_as, endpoint, switch_type, progid, coclass, iid_is, represent_as,
|
||||||
|
transmit_as, import, include, cpp_quote.
|
||||||
|
|
||||||
|
=head2 PIDL Specific properties
|
||||||
|
|
||||||
|
=over 4
|
||||||
|
|
||||||
|
=item public
|
||||||
|
|
||||||
|
The [public] property on a structure or union is a pidl extension that
|
||||||
|
forces the generated pull/push functions to be non-static. This allows
|
||||||
|
you to declare types that can be used between modules. If you don't
|
||||||
|
specify [public] then pull/push functions for other than top-level
|
||||||
|
functions are declared static.
|
||||||
|
|
||||||
|
=item noprint
|
||||||
|
|
||||||
|
The [noprint] property is a pidl extension that allows you to specify
|
||||||
|
that pidl should not generate a ndr_print_*() function for that
|
||||||
|
structure or union. This is used when you wish to define your own
|
||||||
|
print function that prints a structure in a nicer manner. A good
|
||||||
|
example is the use of [noprint] on dom_sid, which allows the
|
||||||
|
pretty-printing of SIDs.
|
||||||
|
|
||||||
|
=item value
|
||||||
|
|
||||||
|
The [value(expression)] property is a pidl extension that allows you
|
||||||
|
to specify the value of a field when it is put on the wire. This
|
||||||
|
allows fields that always have a well-known value to be automatically
|
||||||
|
filled in, thus making the API more programmer friendly. The
|
||||||
|
expression can be any C expression.
|
||||||
|
|
||||||
|
=item relative
|
||||||
|
|
||||||
|
The [relative] property can be supplied on a pointer. When it is used
|
||||||
|
it declares the pointer as a spoolss style "relative" pointer, which
|
||||||
|
means it appears on the wire as an offset within the current
|
||||||
|
encapsulating structure. This is not part of normal IDL/NDR, but it is
|
||||||
|
a very useful extension as it avoids the manual encoding of many
|
||||||
|
complex structures.
|
||||||
|
|
||||||
|
=item subcontext(length)
|
||||||
|
|
||||||
|
Specifies that a size of I<length>
|
||||||
|
bytes should be read, followed by a blob of that size,
|
||||||
|
which will be parsed as NDR.
|
||||||
|
|
||||||
|
subcontext() is deprecated now, and should not be used in new code.
|
||||||
|
Instead, use represent_as() or transmit_as().
|
||||||
|
|
||||||
|
=item flag
|
||||||
|
|
||||||
|
Specify boolean options, mostly used for
|
||||||
|
low-level NDR options. Several options
|
||||||
|
can be specified using the | character.
|
||||||
|
Note that flags are inherited by substructures!
|
||||||
|
|
||||||
|
=item nodiscriminant
|
||||||
|
|
||||||
|
The [nodiscriminant] property on a union means that the usual uint16
|
||||||
|
discriminent field at the start of the union on the wire is
|
||||||
|
omitted. This is not normally allowed in IDL/NDR, but is used for some
|
||||||
|
spoolss structures.
|
||||||
|
|
||||||
|
=item charset(name)
|
||||||
|
|
||||||
|
Specify that the array or string uses the specified
|
||||||
|
charset. If this attribute is specified, pidl will
|
||||||
|
take care of converting the character data from this format
|
||||||
|
to the host format. Commonly used values are UCS2, DOS and UTF8.
|
||||||
|
|
||||||
|
=back
|
||||||
|
|
||||||
|
=head2 Unsupported MIDL properties or statements
|
||||||
|
|
||||||
|
aggregatable, appobject, async_uuid, bindable, control,
|
||||||
|
defaultbind, defaultcollelem, defaultvalue, defaultvtable, dispinterface,
|
||||||
|
displaybind, dual, entry, first_is, helpcontext, helpfile, helpstringcontext,
|
||||||
|
helpstringdll, hidden, idl_module, idl_quote, id, immediatebind, importlib,
|
||||||
|
includelib, last_is, lcid, licensed, max_is, module,
|
||||||
|
ms_union, no_injected_text, nonbrowsable, noncreatable, nonextensible, odl,
|
||||||
|
oleautomation, optional, pragma, propget, propputref, propput, readonly,
|
||||||
|
requestedit, restricted, retval, source, uidefault,
|
||||||
|
usesgetlasterror, vararg, vi_progid, wire_marshal.
|
||||||
|
|
||||||
|
=head1 EXAMPLES
|
||||||
|
|
||||||
|
# Generating an Wireshark parser
|
||||||
|
$ ./pidl --ws-parser -- atsvc.idl
|
||||||
|
|
||||||
|
# Generating a TDR parser and header
|
||||||
|
$ ./pidl --tdr-parser --header -- regf.idl
|
||||||
|
|
||||||
|
# Generating a Samba3 client and server
|
||||||
|
$ ./pidl --samba3-ndr-client --samba3-ndr-server -- dfs.idl
|
||||||
|
|
||||||
|
# Generating a Samba4 NDR parser, client and server
|
||||||
|
$ ./pidl --ndr-parser --ndr-client --ndr-server -- samr.idl
|
||||||
|
|
||||||
|
=head1 SEE ALSO
|
||||||
|
|
||||||
|
L<http://msdn.microsoft.com/library/en-us/rpc/rpc/field_attributes.asp>,
|
||||||
|
L<http://wiki.wireshark.org/DCE/RPC>,
|
||||||
|
L<http://www.samba.org/>,
|
||||||
|
L<yapp(1)>
|
||||||
|
|
||||||
|
=head1 LICENSE
|
||||||
|
|
||||||
|
pidl is licensed under the GNU General Public License L<http://www.gnu.org/licenses/gpl.html>.
|
||||||
|
|
||||||
|
=head1 AUTHOR
|
||||||
|
|
||||||
|
pidl was written by Andrew Tridgell, Stefan Metzmacher, Tim Potter and Jelmer
|
||||||
|
Vernooij. The current maintainer is Jelmer Vernooij.
|
||||||
|
|
||||||
|
This manpage was written by Jelmer Vernooij, partially based on the original
|
||||||
|
pidl README by Andrew Tridgell.
|
||||||
|
|
||||||
|
This code has been modified for use with the COMROGUE operating system by Eric J. Bowersox.
|
||||||
|
|
||||||
|
=cut
|
||||||
|
|
||||||
|
|
||||||
|
use strict;
|
||||||
|
use FindBin qw($RealBin $Script);
|
||||||
|
use lib "$RealBin/lib";
|
||||||
|
use lib "$RealBin/../share/perl5";
|
||||||
|
use Getopt::Long;
|
||||||
|
use File::Basename;
|
||||||
|
use Parse::Pidl qw ( $VERSION );
|
||||||
|
use Parse::Pidl::Util;
|
||||||
|
use Parse::Pidl::ODL;
|
||||||
|
|
||||||
|
#####################################################################
|
||||||
|
# save a data structure into a file
|
||||||
|
sub SaveStructure($$)
|
||||||
|
{
|
||||||
|
my($filename,$v) = @_;
|
||||||
|
FileSave($filename, Parse::Pidl::Util::MyDumper($v));
|
||||||
|
}
|
||||||
|
|
||||||
|
#####################################################################
|
||||||
|
# load a data structure from a file (as saved with SaveStructure)
|
||||||
|
sub LoadStructure($)
|
||||||
|
{
|
||||||
|
my $f = shift;
|
||||||
|
my $contents = FileLoad($f);
|
||||||
|
defined $contents || return undef;
|
||||||
|
return eval "$contents";
|
||||||
|
}
|
||||||
|
|
||||||
|
#####################################################################
|
||||||
|
# read a file into a string
|
||||||
|
sub FileLoad($)
|
||||||
|
{
|
||||||
|
my($filename) = shift;
|
||||||
|
local(*INPUTFILE);
|
||||||
|
open(INPUTFILE, $filename) || return undef;
|
||||||
|
my($saved_delim) = $/;
|
||||||
|
undef $/;
|
||||||
|
my($data) = <INPUTFILE>;
|
||||||
|
close(INPUTFILE);
|
||||||
|
$/ = $saved_delim;
|
||||||
|
return $data;
|
||||||
|
}
|
||||||
|
|
||||||
|
#####################################################################
|
||||||
|
# write a string into a file
|
||||||
|
sub FileSave($$)
|
||||||
|
{
|
||||||
|
my($filename) = shift;
|
||||||
|
my($v) = shift;
|
||||||
|
local(*FILE);
|
||||||
|
open(FILE, ">$filename") || die "can't open $filename";
|
||||||
|
print FILE $v;
|
||||||
|
close(FILE);
|
||||||
|
}
|
||||||
|
|
||||||
|
my(@opt_incdirs) = ();
|
||||||
|
my($opt_help) = 0;
|
||||||
|
my($opt_version) = 0;
|
||||||
|
my($opt_parse_idl_tree) = 0;
|
||||||
|
my($opt_dump_idl_tree);
|
||||||
|
my($opt_dump_ndr_tree);
|
||||||
|
my($opt_dump_idl) = 0;
|
||||||
|
my($opt_diff) = 0;
|
||||||
|
my($opt_header);
|
||||||
|
my($opt_samba3_header);
|
||||||
|
my($opt_samba3_parser);
|
||||||
|
my($opt_samba3_server);
|
||||||
|
my($opt_samba3_ndr_client);
|
||||||
|
my($opt_samba3_ndr_server);
|
||||||
|
my($opt_template) = 0;
|
||||||
|
my($opt_client);
|
||||||
|
my($opt_typelib);
|
||||||
|
my($opt_server);
|
||||||
|
my($opt_ndr_parser);
|
||||||
|
my($opt_tdr_parser);
|
||||||
|
my($opt_ws_parser);
|
||||||
|
my($opt_python);
|
||||||
|
my($opt_quiet) = 0;
|
||||||
|
my($opt_outputdir) = '.';
|
||||||
|
my($opt_verbose) = 0;
|
||||||
|
my($opt_warn_compat) = 0;
|
||||||
|
my($opt_dcom_proxy);
|
||||||
|
my($opt_com_header);
|
||||||
|
my($opt_comrogue_header);
|
||||||
|
|
||||||
|
#########################################
|
||||||
|
# display help text
|
||||||
|
sub ShowHelp()
|
||||||
|
{
|
||||||
|
print "perl IDL parser and code generator\n";
|
||||||
|
ShowVersion();
|
||||||
|
print"
|
||||||
|
Copyright (C) Andrew Tridgell <tridge\@samba.org>
|
||||||
|
Copyright (C) Jelmer Vernooij <jelmer\@samba.org>
|
||||||
|
|
||||||
|
Usage: $Script [options] [--] <idlfile> [<idlfile>...]
|
||||||
|
|
||||||
|
Generic Options:
|
||||||
|
--help this help page
|
||||||
|
--version show pidl version
|
||||||
|
--outputdir=OUTDIR put output in OUTDIR/ [.]
|
||||||
|
--warn-compat warn about incompatibility with other compilers
|
||||||
|
--quiet be quiet
|
||||||
|
--verbose be verbose
|
||||||
|
--includedir DIR search DIR for included files
|
||||||
|
|
||||||
|
Debugging:
|
||||||
|
--dump-idl-tree[=FILE] dump internal representation to file [BASENAME.pidl]
|
||||||
|
--parse-idl-tree read internal representation instead of IDL
|
||||||
|
--dump-ndr-tree[=FILE] dump internal NDR data tree to file [BASENAME.ndr]
|
||||||
|
--dump-idl regenerate IDL file
|
||||||
|
--diff run diff on original IDL and dumped output
|
||||||
|
--typelib print type information
|
||||||
|
|
||||||
|
Samba 4 output:
|
||||||
|
--header[=OUTFILE] create generic header file [BASENAME.h]
|
||||||
|
--ndr-parser[=OUTFILE] create a C NDR parser [ndr_BASENAME.c]
|
||||||
|
--client[=OUTFILE] create a C NDR client [ndr_BASENAME_c.c]
|
||||||
|
--tdr-parser[=OUTFILE] create a C TDR parser [tdr_BASENAME.c]
|
||||||
|
--python[=OUTFILE] create python wrapper file [py_BASENAME.c]
|
||||||
|
--server[=OUTFILE] create server boilerplate [ndr_BASENAME_s.c]
|
||||||
|
--template print a template for a pipe
|
||||||
|
--dcom-proxy[=OUTFILE] create DCOM proxy [ndr_BASENAME_p.c]
|
||||||
|
--com-header[=OUTFILE] create header for COM [com_BASENAME.h]
|
||||||
|
|
||||||
|
Samba 3 output:
|
||||||
|
--samba3-ndr-client[=OUTF] create client calls for Samba3
|
||||||
|
using Samba4's NDR code [cli_BASENAME.c]
|
||||||
|
--samba3-ndr-server[=OUTF] create server call wrapper for Samba3
|
||||||
|
using Samba4's NDR code [srv_BASENAME.c]
|
||||||
|
|
||||||
|
Wireshark parsers:
|
||||||
|
--ws-parser[=OUTFILE] create Wireshark parser and header
|
||||||
|
|
||||||
|
COMROGUE:
|
||||||
|
--comrogue-header[=OUTFILE] create header for COMROGUE interface
|
||||||
|
[BASENAME.h]
|
||||||
|
\n";
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#########################################
|
||||||
|
# Display version
|
||||||
|
sub ShowVersion()
|
||||||
|
{
|
||||||
|
print "perl IDL version $VERSION\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
# main program
|
||||||
|
my $result = GetOptions (
|
||||||
|
'help|h|?' => \$opt_help,
|
||||||
|
'version' => \$opt_version,
|
||||||
|
'outputdir=s' => \$opt_outputdir,
|
||||||
|
'dump-idl' => \$opt_dump_idl,
|
||||||
|
'dump-idl-tree:s' => \$opt_dump_idl_tree,
|
||||||
|
'parse-idl-tree' => \$opt_parse_idl_tree,
|
||||||
|
'dump-ndr-tree:s' => \$opt_dump_ndr_tree,
|
||||||
|
'samba3-ndr-client:s' => \$opt_samba3_ndr_client,
|
||||||
|
'samba3-ndr-server:s' => \$opt_samba3_ndr_server,
|
||||||
|
'header:s' => \$opt_header,
|
||||||
|
'server:s' => \$opt_server,
|
||||||
|
'typelib:s' => \$opt_typelib,
|
||||||
|
'tdr-parser:s' => \$opt_tdr_parser,
|
||||||
|
'template' => \$opt_template,
|
||||||
|
'ndr-parser:s' => \$opt_ndr_parser,
|
||||||
|
'client:s' => \$opt_client,
|
||||||
|
'ws-parser:s' => \$opt_ws_parser,
|
||||||
|
'python' => \$opt_python,
|
||||||
|
'diff' => \$opt_diff,
|
||||||
|
'dcom-proxy:s' => \$opt_dcom_proxy,
|
||||||
|
'com-header:s' => \$opt_com_header,
|
||||||
|
'comrogue-header:s' => \$opt_comrogue_header,
|
||||||
|
'quiet' => \$opt_quiet,
|
||||||
|
'verbose' => \$opt_verbose,
|
||||||
|
'warn-compat' => \$opt_warn_compat,
|
||||||
|
'includedir=s@' => \@opt_incdirs
|
||||||
|
);
|
||||||
|
|
||||||
|
if (not $result) {
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($opt_help) {
|
||||||
|
ShowHelp();
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($opt_version) {
|
||||||
|
ShowVersion();
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
sub process_imports($)
|
||||||
|
{
|
||||||
|
my $pidl = shift;
|
||||||
|
foreach my $d (@{$pidl})
|
||||||
|
{
|
||||||
|
next unless $d->{TYPE} eq "IMPORT";
|
||||||
|
foreach my $p (@{$d->{PATHS}}) {
|
||||||
|
my $f = Parse::Pidl::IDL::parse_file($p, \@opt_incdirs);
|
||||||
|
defined @$f || die "Failed to parse $p";
|
||||||
|
my $basename = basename($p, ".idl");
|
||||||
|
Parse::Pidl::Typelist::LoadIdl($f, $basename);
|
||||||
|
process_imports($f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sub process_file($)
|
||||||
|
{
|
||||||
|
my $idl_file = shift;
|
||||||
|
my $outputdir = $opt_outputdir;
|
||||||
|
my $pidl;
|
||||||
|
my $ndr;
|
||||||
|
|
||||||
|
my $basename = basename($idl_file, ".idl");
|
||||||
|
|
||||||
|
unless ($opt_quiet) { print "Compiling $idl_file\n"; }
|
||||||
|
|
||||||
|
if ($opt_parse_idl_tree) {
|
||||||
|
$pidl = LoadStructure($idl_file);
|
||||||
|
defined $pidl || die "Failed to load $idl_file";
|
||||||
|
} else {
|
||||||
|
require Parse::Pidl::IDL;
|
||||||
|
|
||||||
|
$pidl = Parse::Pidl::IDL::parse_file($idl_file, \@opt_incdirs);
|
||||||
|
defined @$pidl || die "Failed to parse $idl_file";
|
||||||
|
}
|
||||||
|
|
||||||
|
require Parse::Pidl::Typelist;
|
||||||
|
Parse::Pidl::Typelist::LoadIdl($pidl, $basename);
|
||||||
|
|
||||||
|
if (defined($opt_dump_idl_tree)) {
|
||||||
|
my($pidl_file) = ($opt_dump_idl_tree or "$outputdir/$basename.pidl");
|
||||||
|
SaveStructure($pidl_file, $pidl) or die "Failed to save $pidl_file\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($opt_dump_idl) {
|
||||||
|
require Parse::Pidl::Dump;
|
||||||
|
print Parse::Pidl::Dump($pidl);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($opt_diff) {
|
||||||
|
my($tempfile) = "$outputdir/$basename.tmp";
|
||||||
|
FileSave($tempfile, IdlDump::Dump($pidl));
|
||||||
|
system("diff -wu $idl_file $tempfile");
|
||||||
|
unlink($tempfile);
|
||||||
|
}
|
||||||
|
|
||||||
|
my $crh_filename = ($opt_comrogue_header or "$outputdir/$basename.h");
|
||||||
|
if (defined($opt_comrogue_header)) {
|
||||||
|
process_imports($pidl);
|
||||||
|
require Parse::Pidl::COMROGUE::Header;
|
||||||
|
my $res = Parse::Pidl::COMROGUE::Header::Parse($pidl,$basename,$idl_file);
|
||||||
|
if ($res) {
|
||||||
|
FileSave($crh_filename, $res);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
my $comh_filename = ($opt_com_header or "$outputdir/com_$basename.h");
|
||||||
|
if (defined($opt_com_header)) {
|
||||||
|
require Parse::Pidl::Samba4::COM::Header;
|
||||||
|
my $res = Parse::Pidl::Samba4::COM::Header::Parse($pidl,"$outputdir/ndr_$basename.h");
|
||||||
|
if ($res) {
|
||||||
|
FileSave($comh_filename, $res);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (defined($opt_dcom_proxy)) {
|
||||||
|
require Parse::Pidl::Samba4::COM::Proxy;
|
||||||
|
my $res = Parse::Pidl::Samba4::COM::Proxy::Parse($pidl,$comh_filename);
|
||||||
|
if ($res) {
|
||||||
|
my ($client) = ($opt_dcom_proxy or "$outputdir/$basename\_p.c");
|
||||||
|
FileSave($client, $res);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($opt_warn_compat) {
|
||||||
|
require Parse::Pidl::Compat;
|
||||||
|
Parse::Pidl::Compat::Check($pidl);
|
||||||
|
}
|
||||||
|
|
||||||
|
$pidl = Parse::Pidl::ODL::ODL2IDL($pidl, dirname($idl_file), \@opt_incdirs);
|
||||||
|
|
||||||
|
if (defined($opt_ws_parser)) {
|
||||||
|
require Parse::Pidl::Wireshark::NDR;
|
||||||
|
|
||||||
|
my $cnffile = $idl_file;
|
||||||
|
$cnffile =~ s/\.idl$/\.cnf/;
|
||||||
|
|
||||||
|
my $generator = new Parse::Pidl::Wireshark::NDR();
|
||||||
|
$generator->Initialize($cnffile);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (defined($opt_ws_parser) or
|
||||||
|
defined($opt_client) or
|
||||||
|
defined($opt_server) or
|
||||||
|
defined($opt_header) or
|
||||||
|
defined($opt_ndr_parser) or
|
||||||
|
defined($opt_python) or
|
||||||
|
defined($opt_dump_ndr_tree) or
|
||||||
|
defined($opt_samba3_header) or
|
||||||
|
defined($opt_samba3_parser) or
|
||||||
|
defined($opt_samba3_server) or
|
||||||
|
defined($opt_samba3_ndr_client) or
|
||||||
|
defined($opt_samba3_ndr_server)) {
|
||||||
|
require Parse::Pidl::NDR;
|
||||||
|
$ndr = Parse::Pidl::NDR::Parse($pidl);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (defined($opt_dump_ndr_tree)) {
|
||||||
|
my($ndr_file) = ($opt_dump_ndr_tree or "$outputdir/$basename.ndr");
|
||||||
|
SaveStructure($ndr_file, $ndr) or die "Failed to save $ndr_file\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
my $gen_header = ($opt_header or "$outputdir/$basename.h");
|
||||||
|
if (defined($opt_header)) {
|
||||||
|
require Parse::Pidl::Samba4::Header;
|
||||||
|
FileSave($gen_header, Parse::Pidl::Samba4::Header::Parse($ndr));
|
||||||
|
}
|
||||||
|
|
||||||
|
my $h_filename = "$outputdir/ndr_$basename.h";
|
||||||
|
my $c_header = "$outputdir/ndr_$basename\_c.h";
|
||||||
|
if (defined($opt_client) or defined($opt_samba3_ndr_client)) {
|
||||||
|
require Parse::Pidl::Samba4::NDR::Client;
|
||||||
|
my ($c_client) = ($opt_client or "$outputdir/ndr_$basename\_c.c");
|
||||||
|
$c_header = $c_client;
|
||||||
|
$c_header =~ s/\.c$/.h/;
|
||||||
|
|
||||||
|
my $generator = new Parse::Pidl::Samba4::NDR::Client();
|
||||||
|
my ($srcd,$hdrd) = $generator->Parse(
|
||||||
|
$ndr,$gen_header,$h_filename,$c_header);
|
||||||
|
|
||||||
|
FileSave($c_client, $srcd);
|
||||||
|
FileSave($c_header, $hdrd);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (defined($opt_python)) {
|
||||||
|
require Parse::Pidl::Samba4::Python;
|
||||||
|
my $generator = new Parse::Pidl::Samba4::Python();
|
||||||
|
my ($prsr) = $generator->Parse($basename, $ndr,
|
||||||
|
"$outputdir/ndr_$basename\_c.h", $h_filename);
|
||||||
|
FileSave("$outputdir/py_$basename.c", $prsr);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (defined($opt_server)) {
|
||||||
|
require Parse::Pidl::Samba4::NDR::Server;
|
||||||
|
|
||||||
|
FileSave(($opt_server or "$outputdir/ndr_$basename\_s.c"), Parse::Pidl::Samba4::NDR::Server::Parse($ndr,$h_filename));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (defined($opt_ndr_parser)) {
|
||||||
|
my $parser_fname = ($opt_ndr_parser or "$outputdir/ndr_$basename.c");
|
||||||
|
require Parse::Pidl::Samba4::NDR::Parser;
|
||||||
|
my $generator = new Parse::Pidl::Samba4::NDR::Parser();
|
||||||
|
my ($header,$parser) = $generator->Parse($ndr, $gen_header, $h_filename);
|
||||||
|
|
||||||
|
FileSave($parser_fname, $parser);
|
||||||
|
FileSave($h_filename, $header);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (defined($opt_ws_parser)) {
|
||||||
|
require Parse::Pidl::Wireshark::NDR;
|
||||||
|
my($eparser) = ($opt_ws_parser or "$outputdir/packet-dcerpc-$basename.c");
|
||||||
|
my $eheader = $eparser;
|
||||||
|
$eheader =~ s/\.c$/\.h/;
|
||||||
|
my $cnffile = $idl_file;
|
||||||
|
$cnffile =~ s/\.idl$/\.cnf/;
|
||||||
|
|
||||||
|
my $generator = new Parse::Pidl::Wireshark::NDR();
|
||||||
|
my ($dp, $dh) = $generator->Parse($ndr, $idl_file, $eheader, $cnffile);
|
||||||
|
FileSave($eparser, $dp) if defined($dp);
|
||||||
|
FileSave($eheader, $dh) if defined($dh);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (defined($opt_tdr_parser)) {
|
||||||
|
my $tdr_parser = ($opt_tdr_parser or "$outputdir/tdr_$basename.c");
|
||||||
|
my $tdr_header = $tdr_parser;
|
||||||
|
$tdr_header =~ s/\.c$/\.h/;
|
||||||
|
require Parse::Pidl::Samba4::TDR;
|
||||||
|
my $generator = new Parse::Pidl::Samba4::TDR();
|
||||||
|
my ($hdr,$prsr) = $generator->Parser($pidl, $tdr_header, $gen_header);
|
||||||
|
FileSave($tdr_parser, $prsr);
|
||||||
|
FileSave($tdr_header, $hdr);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (defined($opt_typelib)) {
|
||||||
|
my $typelib = ($opt_typelib or "$outputdir/$basename.tlb");
|
||||||
|
require Parse::Pidl::Typelist;
|
||||||
|
FileSave($typelib, Parse::Pidl::Typelist::GenerateTypeLib());
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($opt_template) {
|
||||||
|
require Parse::Pidl::Samba4::Template;
|
||||||
|
print Parse::Pidl::Samba4::Template::Parse($pidl);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (defined($opt_samba3_ndr_client)) {
|
||||||
|
my $client = ($opt_samba3_ndr_client or "$outputdir/cli_$basename.c");
|
||||||
|
my $header = $client; $header =~ s/\.c$/\.h/;
|
||||||
|
require Parse::Pidl::Samba3::ClientNDR;
|
||||||
|
my $generator = new Parse::Pidl::Samba3::ClientNDR();
|
||||||
|
my ($c_code,$h_code) = $generator->Parse($ndr, $header, $c_header);
|
||||||
|
FileSave($client, $c_code);
|
||||||
|
FileSave($header, $h_code);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (defined($opt_samba3_ndr_server)) {
|
||||||
|
my $server = ($opt_samba3_ndr_server or "$outputdir/srv_$basename.c");
|
||||||
|
my $header = $server; $header =~ s/\.c$/\.h/;
|
||||||
|
require Parse::Pidl::Samba3::ServerNDR;
|
||||||
|
my ($c_code,$h_code) = Parse::Pidl::Samba3::ServerNDR::Parse($ndr, $header, $h_filename);
|
||||||
|
FileSave($server, $c_code);
|
||||||
|
FileSave($header, $h_code);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (scalar(@ARGV) == 0) {
|
||||||
|
print "$Script: no input files\n";
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
process_file($_) foreach (@ARGV);
|
181
tools/pidl/tests/Util.pm
Normal file
181
tools/pidl/tests/Util.pm
Normal file
|
@ -0,0 +1,181 @@
|
||||||
|
# Some simple utility functions for pidl tests
|
||||||
|
# Copyright (C) 2005-2006 Jelmer Vernooij
|
||||||
|
# Published under the GNU General Public License
|
||||||
|
|
||||||
|
package Util;
|
||||||
|
|
||||||
|
require Exporter;
|
||||||
|
@ISA = qw(Exporter);
|
||||||
|
@EXPORT = qw(test_samba4_ndr test_warnings test_errors);
|
||||||
|
|
||||||
|
use strict;
|
||||||
|
|
||||||
|
use FindBin qw($RealBin);
|
||||||
|
use lib "$RealBin/../lib";
|
||||||
|
|
||||||
|
use Parse::Pidl::Samba4 qw(is_intree);
|
||||||
|
|
||||||
|
use Parse::Pidl;
|
||||||
|
my $warnings = "";
|
||||||
|
undef &Parse::Pidl::warning;
|
||||||
|
*Parse::Pidl::warning = sub {
|
||||||
|
my ($e, $l) = @_;
|
||||||
|
if (defined($e)) {
|
||||||
|
$warnings .= "$e->{FILE}:$e->{LINE}: $l\n";
|
||||||
|
} else {
|
||||||
|
$warnings .= "$l\n";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
my $errors = "";
|
||||||
|
undef &Parse::Pidl::error;
|
||||||
|
*Parse::Pidl::error = sub {
|
||||||
|
my ($e, $l) = @_;
|
||||||
|
if (defined($e)) {
|
||||||
|
$errors .= "$e->{FILE}:$e->{LINE}: $l\n";
|
||||||
|
} else {
|
||||||
|
$errors .= "$l\n";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
use Test::More;
|
||||||
|
use Parse::Pidl::IDL;
|
||||||
|
use Parse::Pidl::NDR;
|
||||||
|
use Parse::Pidl::Samba4::NDR::Parser;
|
||||||
|
use Parse::Pidl::Samba4::Header;
|
||||||
|
|
||||||
|
# Generate a Samba4 parser for an IDL fragment and run it with a specified
|
||||||
|
# piece of code to check whether the parser works as expected
|
||||||
|
sub test_samba4_ndr
|
||||||
|
{
|
||||||
|
my ($name,$idl,$c,$extra) = @_;
|
||||||
|
|
||||||
|
$extra = "" unless defined($extra);
|
||||||
|
|
||||||
|
my $pidl = Parse::Pidl::IDL::parse_string("interface echo { $idl }; ", "<$name>");
|
||||||
|
ok(defined($pidl), "($name) parse idl");
|
||||||
|
|
||||||
|
my $pndr = Parse::Pidl::NDR::Parse($pidl);
|
||||||
|
ok(defined($pndr), "($name) generate NDR tree");
|
||||||
|
|
||||||
|
my $header = Parse::Pidl::Samba4::Header::Parse($pndr);
|
||||||
|
ok(defined($header), "($name) generate generic header");
|
||||||
|
|
||||||
|
my $generator = new Parse::Pidl::Samba4::NDR::Parser();
|
||||||
|
my ($ndrheader,$ndrparser) = $generator->Parse($pndr, undef, undef);
|
||||||
|
ok(defined($ndrparser), "($name) generate NDR parser");
|
||||||
|
ok(defined($ndrheader), "($name) generate NDR header");
|
||||||
|
|
||||||
|
SKIP: {
|
||||||
|
|
||||||
|
my $flags;
|
||||||
|
if (system("pkg-config --exists ndr") == 0 and !is_intree()) {
|
||||||
|
$flags = `pkg-config --libs --cflags ndr`;
|
||||||
|
} else {
|
||||||
|
skip "no samba environment available, skipping compilation", 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
my $main = "
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <util/data_blob.h>
|
||||||
|
|
||||||
|
/* header start */
|
||||||
|
$header
|
||||||
|
/* header end */
|
||||||
|
|
||||||
|
/* ndrheader start */
|
||||||
|
$ndrheader
|
||||||
|
/* ndrheader end */
|
||||||
|
|
||||||
|
/* extra start */
|
||||||
|
$extra
|
||||||
|
/* extra end */
|
||||||
|
|
||||||
|
/* ndrparser start */
|
||||||
|
$ndrparser
|
||||||
|
/* ndrparser end */
|
||||||
|
|
||||||
|
/* main start */
|
||||||
|
int main(int argc, const char **argv)
|
||||||
|
{
|
||||||
|
TALLOC_CTX *mem_ctx = talloc_init(NULL);
|
||||||
|
|
||||||
|
$c
|
||||||
|
|
||||||
|
talloc_free(mem_ctx);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
/* main end */
|
||||||
|
\n";
|
||||||
|
|
||||||
|
my $main_debug = "# ".join("\n# ", split("\n", $main));
|
||||||
|
|
||||||
|
my $test_data_prefix = $ENV{TEST_DATA_PREFIX};
|
||||||
|
my $outfile;
|
||||||
|
if (defined($test_data_prefix)) {
|
||||||
|
$outfile = "$test_data_prefix/test-$name";
|
||||||
|
} else {
|
||||||
|
$outfile = "./test-$name";
|
||||||
|
}
|
||||||
|
|
||||||
|
my $cflags = $ENV{CFLAGS};
|
||||||
|
unless (defined($cflags)) {
|
||||||
|
$cflags = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
my $ldflags = $ENV{LDFLAGS};
|
||||||
|
unless (defined($ldflags)) {
|
||||||
|
$ldflags = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
my $cc = $ENV{CC};
|
||||||
|
unless (defined($cc)) {
|
||||||
|
$cc = "cc";
|
||||||
|
}
|
||||||
|
|
||||||
|
my $cmd = "$cc $cflags -x c - -o $outfile $flags $ldflags";
|
||||||
|
$cmd =~ s/\n//g;
|
||||||
|
open CC, "|$cmd";
|
||||||
|
print CC $main;
|
||||||
|
close CC;
|
||||||
|
|
||||||
|
ok(-f $outfile, "($name) compile");
|
||||||
|
|
||||||
|
my $ret = system($outfile, ()) >> 8;
|
||||||
|
print "# code:\n#\n$main_debug\n" if ($ret != 0);
|
||||||
|
print "# cmd: $cmd\n" if ($ret != 0);
|
||||||
|
print "# return code: $ret\n" if ($ret != 0);
|
||||||
|
|
||||||
|
ok($ret == 0, "($name) run");
|
||||||
|
|
||||||
|
ok(unlink($outfile), "($name) remove");
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sub test_warnings($$)
|
||||||
|
{
|
||||||
|
my ($exp, $code) = @_;
|
||||||
|
|
||||||
|
$warnings = "";
|
||||||
|
|
||||||
|
$code->();
|
||||||
|
|
||||||
|
is($warnings, $exp);
|
||||||
|
}
|
||||||
|
|
||||||
|
sub test_errors($$)
|
||||||
|
{
|
||||||
|
my ($exp, $code) = @_;
|
||||||
|
$errors = "";
|
||||||
|
$code->();
|
||||||
|
|
||||||
|
is($errors, $exp);
|
||||||
|
}
|
||||||
|
|
||||||
|
1;
|
21
tools/pidl/tests/cutil.pl
Executable file
21
tools/pidl/tests/cutil.pl
Executable file
|
@ -0,0 +1,21 @@
|
||||||
|
#!/usr/bin/perl
|
||||||
|
# (C) 2007 Jelmer Vernooij <jelmer@samba.org>
|
||||||
|
# Published under the GNU General Public License
|
||||||
|
use strict;
|
||||||
|
use warnings;
|
||||||
|
|
||||||
|
use Test::More tests => 7;
|
||||||
|
use FindBin qw($RealBin);
|
||||||
|
use lib "$RealBin";
|
||||||
|
use Util;
|
||||||
|
use Parse::Pidl::Util qw(MyDumper);
|
||||||
|
use Parse::Pidl::CUtil qw(get_pointer_to get_value_of);
|
||||||
|
|
||||||
|
is("&foo", get_pointer_to("foo"));
|
||||||
|
is("&(&foo)", get_pointer_to(get_pointer_to("foo")));
|
||||||
|
is("*foo", get_pointer_to("**foo"));
|
||||||
|
is("foo", get_pointer_to("*foo"));
|
||||||
|
|
||||||
|
is("foo", get_value_of("&foo"));
|
||||||
|
is("*foo", get_value_of("foo"));
|
||||||
|
is("**foo", get_value_of("*foo"));
|
15
tools/pidl/tests/dump.pl
Executable file
15
tools/pidl/tests/dump.pl
Executable file
|
@ -0,0 +1,15 @@
|
||||||
|
#!/usr/bin/perl
|
||||||
|
# (C) 2007 Jelmer Vernooij <jelmer@samba.org>
|
||||||
|
# Published under the GNU General Public License
|
||||||
|
use strict;
|
||||||
|
use warnings;
|
||||||
|
|
||||||
|
use Test::More tests => 1;
|
||||||
|
use FindBin qw($RealBin);
|
||||||
|
use lib "$RealBin";
|
||||||
|
use Util;
|
||||||
|
use Parse::Pidl::Dump qw(DumpStruct);
|
||||||
|
|
||||||
|
is (DumpStruct({ NAME => "foo", ELEMENTS => []}),
|
||||||
|
"struct foo {\n}");
|
||||||
|
|
108
tools/pidl/tests/header.pl
Executable file
108
tools/pidl/tests/header.pl
Executable file
|
@ -0,0 +1,108 @@
|
||||||
|
#!/usr/bin/perl
|
||||||
|
# (C) 2007 Jelmer Vernooij <jelmer@samba.org>
|
||||||
|
# Published under the GNU General Public License
|
||||||
|
use strict;
|
||||||
|
use warnings;
|
||||||
|
|
||||||
|
use Test::More tests => 27;
|
||||||
|
use FindBin qw($RealBin);
|
||||||
|
use lib "$RealBin";
|
||||||
|
use Util;
|
||||||
|
use Parse::Pidl::Util qw(MyDumper);
|
||||||
|
use Parse::Pidl::Samba4::Header qw(
|
||||||
|
GenerateFunctionInEnv GenerateFunctionOutEnv GenerateStructEnv
|
||||||
|
EnvSubstituteValue);
|
||||||
|
use Parse::Pidl::IDL qw(parse_string);
|
||||||
|
use Parse::Pidl::NDR;
|
||||||
|
|
||||||
|
sub parse_idl($)
|
||||||
|
{
|
||||||
|
my $text = shift;
|
||||||
|
my $idl = Parse::Pidl::IDL::parse_string($text, "nofile");
|
||||||
|
my $ndr = Parse::Pidl::NDR::Parse($idl);
|
||||||
|
return Parse::Pidl::Samba4::Header::Parse($ndr);
|
||||||
|
}
|
||||||
|
|
||||||
|
like(parse_idl(""), qr/\/\* header auto-generated by pidl \*\/\n/sm, "includes work");
|
||||||
|
like(parse_idl("interface x {}"), qr/\/\* header auto-generated by pidl \*\/\n/sm, "simple empty interface doesn't cause overhead");
|
||||||
|
like(parse_idl("interface p { typedef struct { int y; } x; };"),
|
||||||
|
qr/.*#ifndef _HEADER_p\n#define _HEADER_p\n.+\n#endif \/\* _HEADER_p \*\/.*/ms, "ifdefs are created");
|
||||||
|
like(parse_idl("interface p { typedef struct { int y; } x; };"),
|
||||||
|
qr/struct x.*{.*int32_t y;.*}.*;/sm, "interface member generated properly");
|
||||||
|
like(parse_idl("interface x { void foo (void); };"),
|
||||||
|
qr/struct foo.*{\s+int _dummy_element;\s+};/sm, "void fn contains dummy element");
|
||||||
|
like(parse_idl("interface x { void foo ([in] uint32 x); };"),
|
||||||
|
qr/struct foo.*{\s+struct\s+{\s+uint32_t x;\s+} in;\s+};/sm, "fn in arg works");
|
||||||
|
like(parse_idl("interface x { void foo ([out] uint32 x); };"),
|
||||||
|
qr/struct foo.*{.*struct\s+{\s+uint32_t x;\s+} out;.*};/sm, "fn out arg works");
|
||||||
|
like(parse_idl("interface x { void foo ([in,out] uint32 x); };"),
|
||||||
|
qr/struct foo.*{.*struct\s+{\s+uint32_t x;\s+} in;\s+struct\s+{\s+uint32_t x;\s+} out;.*};/sm, "fn in,out arg works");
|
||||||
|
like(parse_idl("interface x { void foo (uint32 x); };"), qr/struct foo.*{.*struct\s+{\s+uint32_t x;\s+} in;\s+struct\s+{\s+uint32_t x;\s+} out;.*};/sm, "fn with no props implies in,out");
|
||||||
|
like(parse_idl("interface p { struct x { int y; }; };"),
|
||||||
|
qr/struct x.*{.*int32_t y;.*}.*;/sm, "interface member generated properly");
|
||||||
|
|
||||||
|
like(parse_idl("interface p { struct x { struct y z; }; };"),
|
||||||
|
qr/struct x.*{.*struct y z;.*}.*;/sm, "tagged type struct member");
|
||||||
|
|
||||||
|
like(parse_idl("interface p { struct x { union y z; }; };"),
|
||||||
|
qr/struct x.*{.*union y z;.*}.*;/sm, "tagged type union member");
|
||||||
|
|
||||||
|
like(parse_idl("interface p { struct x { }; };"),
|
||||||
|
qr/struct x.*{.*char _empty_;.*}.*;/sm, "empty struct");
|
||||||
|
|
||||||
|
like(parse_idl("interface p { struct x; };"),
|
||||||
|
qr/struct x;/sm, "struct declaration");
|
||||||
|
|
||||||
|
like(parse_idl("interface p { typedef struct x { int p; } x; };"),
|
||||||
|
qr/struct x.*{.*int32_t p;.*};/sm, "double struct declaration");
|
||||||
|
|
||||||
|
like(parse_idl("cpp_quote(\"some-foo\")"),
|
||||||
|
qr/some-foo/sm, "cpp quote");
|
||||||
|
|
||||||
|
# Make sure GenerateFunctionInEnv and GenerateFunctionOutEnv work
|
||||||
|
my $fn = { ELEMENTS => [ { DIRECTION => ["in"], NAME => "foo" } ] };
|
||||||
|
is_deeply({ "foo" => "r->in.foo" }, GenerateFunctionInEnv($fn));
|
||||||
|
|
||||||
|
$fn = { ELEMENTS => [ { DIRECTION => ["out"], NAME => "foo" } ] };
|
||||||
|
is_deeply({ "foo" => "r->out.foo" }, GenerateFunctionOutEnv($fn));
|
||||||
|
|
||||||
|
$fn = { ELEMENTS => [ { DIRECTION => ["out", "in"], NAME => "foo" } ] };
|
||||||
|
is_deeply({ "foo" => "r->in.foo" }, GenerateFunctionInEnv($fn));
|
||||||
|
|
||||||
|
$fn = { ELEMENTS => [ { DIRECTION => ["out", "in"], NAME => "foo" } ] };
|
||||||
|
is_deeply({ "foo" => "r->out.foo" }, GenerateFunctionOutEnv($fn));
|
||||||
|
|
||||||
|
$fn = { ELEMENTS => [ { DIRECTION => ["in"], NAME => "foo" } ] };
|
||||||
|
is_deeply({ "foo" => "r->in.foo" }, GenerateFunctionOutEnv($fn));
|
||||||
|
|
||||||
|
$fn = { ELEMENTS => [ { DIRECTION => ["out"], NAME => "foo" } ] };
|
||||||
|
is_deeply({ }, GenerateFunctionInEnv($fn));
|
||||||
|
|
||||||
|
$fn = { ELEMENTS => [ { NAME => "foo" }, { NAME => "bar" } ] };
|
||||||
|
is_deeply({ foo => "r->foo", bar => "r->bar", this => "r" },
|
||||||
|
GenerateStructEnv($fn, "r"));
|
||||||
|
|
||||||
|
$fn = { ELEMENTS => [ { NAME => "foo" }, { NAME => "bar" } ] };
|
||||||
|
is_deeply({ foo => "some->complex.variable->foo",
|
||||||
|
bar => "some->complex.variable->bar",
|
||||||
|
this => "some->complex.variable" },
|
||||||
|
GenerateStructEnv($fn, "some->complex.variable"));
|
||||||
|
|
||||||
|
$fn = { ELEMENTS => [ { NAME => "foo", PROPERTIES => { value => 3 }} ] };
|
||||||
|
|
||||||
|
my $env = GenerateStructEnv($fn, "r");
|
||||||
|
EnvSubstituteValue($env, $fn);
|
||||||
|
is_deeply($env, { foo => 3, this => "r" });
|
||||||
|
|
||||||
|
$fn = { ELEMENTS => [ { NAME => "foo" }, { NAME => "bar" } ] };
|
||||||
|
$env = GenerateStructEnv($fn, "r");
|
||||||
|
EnvSubstituteValue($env, $fn);
|
||||||
|
is_deeply($env, { foo => 'r->foo', bar => 'r->bar', this => "r" });
|
||||||
|
|
||||||
|
$fn = { ELEMENTS => [ { NAME => "foo", PROPERTIES => { value => 0 }} ] };
|
||||||
|
|
||||||
|
$env = GenerateStructEnv($fn, "r");
|
||||||
|
EnvSubstituteValue($env, $fn);
|
||||||
|
is_deeply($env, { foo => 0, this => "r" });
|
||||||
|
|
||||||
|
|
561
tools/pidl/tests/ndr.pl
Executable file
561
tools/pidl/tests/ndr.pl
Executable file
|
@ -0,0 +1,561 @@
|
||||||
|
#!/usr/bin/perl
|
||||||
|
# (C) 2007 Jelmer Vernooij <jelmer@samba.org>
|
||||||
|
# Published under the GNU General Public License
|
||||||
|
use strict;
|
||||||
|
use warnings;
|
||||||
|
|
||||||
|
use Test::More tests => 47;
|
||||||
|
use FindBin qw($RealBin);
|
||||||
|
use lib "$RealBin";
|
||||||
|
use Util;
|
||||||
|
use Parse::Pidl::Util qw(MyDumper);
|
||||||
|
use Parse::Pidl::NDR qw(GetElementLevelTable ParseElement align_type mapToScalar ParseType can_contain_deferred);
|
||||||
|
|
||||||
|
# Case 1
|
||||||
|
|
||||||
|
my $e = {
|
||||||
|
'FILE' => 'foo.idl',
|
||||||
|
'NAME' => 'v',
|
||||||
|
'PROPERTIES' => {},
|
||||||
|
'POINTERS' => 0,
|
||||||
|
'TYPE' => 'uint8',
|
||||||
|
'PARENT' => { TYPE => 'STRUCT' },
|
||||||
|
'LINE' => 42 };
|
||||||
|
|
||||||
|
is_deeply(GetElementLevelTable($e, "unique", 0), [
|
||||||
|
{
|
||||||
|
'IS_DEFERRED' => 0,
|
||||||
|
'LEVEL_INDEX' => 0,
|
||||||
|
'DATA_TYPE' => 'uint8',
|
||||||
|
'CONTAINS_DEFERRED' => 0,
|
||||||
|
'TYPE' => 'DATA',
|
||||||
|
'IS_SURROUNDING' => 0,
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
|
||||||
|
my $ne = ParseElement($e, "unique", 0);
|
||||||
|
is($ne->{ORIGINAL}, $e);
|
||||||
|
is($ne->{NAME}, "v");
|
||||||
|
is($ne->{ALIGN}, 1);
|
||||||
|
is($ne->{TYPE}, "uint8");
|
||||||
|
is_deeply($ne->{LEVELS}, [
|
||||||
|
{
|
||||||
|
'IS_DEFERRED' => 0,
|
||||||
|
'LEVEL_INDEX' => 0,
|
||||||
|
'DATA_TYPE' => 'uint8',
|
||||||
|
'CONTAINS_DEFERRED' => 0,
|
||||||
|
'TYPE' => 'DATA',
|
||||||
|
'IS_SURROUNDING' => 0,
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
|
||||||
|
# Case 2 : pointers
|
||||||
|
#
|
||||||
|
$e = {
|
||||||
|
'FILE' => 'foo.idl',
|
||||||
|
'NAME' => 'v',
|
||||||
|
'PROPERTIES' => {"unique" => 1},
|
||||||
|
'POINTERS' => 1,
|
||||||
|
'PARENT' => { TYPE => 'STRUCT' },
|
||||||
|
'TYPE' => 'uint8',
|
||||||
|
'LINE' => 42 };
|
||||||
|
|
||||||
|
is_deeply(GetElementLevelTable($e, "unique", 0), [
|
||||||
|
{
|
||||||
|
LEVEL_INDEX => 0,
|
||||||
|
IS_DEFERRED => 0,
|
||||||
|
TYPE => 'POINTER',
|
||||||
|
POINTER_TYPE => "unique",
|
||||||
|
POINTER_INDEX => 0,
|
||||||
|
LEVEL => 'EMBEDDED'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'IS_DEFERRED' => 1,
|
||||||
|
'LEVEL_INDEX' => 1,
|
||||||
|
'DATA_TYPE' => 'uint8',
|
||||||
|
'CONTAINS_DEFERRED' => 0,
|
||||||
|
'TYPE' => 'DATA',
|
||||||
|
'IS_SURROUNDING' => 0,
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
|
||||||
|
# Case 3 : double pointers
|
||||||
|
#
|
||||||
|
$e = {
|
||||||
|
'FILE' => 'foo.idl',
|
||||||
|
'NAME' => 'v',
|
||||||
|
'PROPERTIES' => {"unique" => 1},
|
||||||
|
'POINTERS' => 2,
|
||||||
|
'TYPE' => 'uint8',
|
||||||
|
'PARENT' => { TYPE => 'STRUCT' },
|
||||||
|
'LINE' => 42 };
|
||||||
|
|
||||||
|
is_deeply(GetElementLevelTable($e, "unique", 0), [
|
||||||
|
{
|
||||||
|
LEVEL_INDEX => 0,
|
||||||
|
IS_DEFERRED => 0,
|
||||||
|
TYPE => 'POINTER',
|
||||||
|
POINTER_TYPE => "unique",
|
||||||
|
POINTER_INDEX => 0,
|
||||||
|
LEVEL => 'EMBEDDED'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
LEVEL_INDEX => 1,
|
||||||
|
IS_DEFERRED => 1,
|
||||||
|
TYPE => 'POINTER',
|
||||||
|
POINTER_TYPE => "unique",
|
||||||
|
POINTER_INDEX => 1,
|
||||||
|
LEVEL => 'EMBEDDED'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'IS_DEFERRED' => 1,
|
||||||
|
'LEVEL_INDEX' => 2,
|
||||||
|
'DATA_TYPE' => 'uint8',
|
||||||
|
'CONTAINS_DEFERRED' => 0,
|
||||||
|
'TYPE' => 'DATA',
|
||||||
|
'IS_SURROUNDING' => 0,
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
|
||||||
|
# Case 3 : ref pointers
|
||||||
|
#
|
||||||
|
$e = {
|
||||||
|
'FILE' => 'foo.idl',
|
||||||
|
'NAME' => 'v',
|
||||||
|
'PROPERTIES' => {"ref" => 1},
|
||||||
|
'POINTERS' => 1,
|
||||||
|
'TYPE' => 'uint8',
|
||||||
|
'PARENT' => { TYPE => 'STRUCT' },
|
||||||
|
'LINE' => 42 };
|
||||||
|
|
||||||
|
is_deeply(GetElementLevelTable($e, "unique", 0), [
|
||||||
|
{
|
||||||
|
LEVEL_INDEX => 0,
|
||||||
|
IS_DEFERRED => 0,
|
||||||
|
TYPE => 'POINTER',
|
||||||
|
POINTER_TYPE => "ref",
|
||||||
|
POINTER_INDEX => 0,
|
||||||
|
LEVEL => 'EMBEDDED'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'IS_DEFERRED' => 1,
|
||||||
|
'LEVEL_INDEX' => 1,
|
||||||
|
'DATA_TYPE' => 'uint8',
|
||||||
|
'CONTAINS_DEFERRED' => 0,
|
||||||
|
'TYPE' => 'DATA',
|
||||||
|
'IS_SURROUNDING' => 0,
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
|
||||||
|
# Case 3 : ref pointers
|
||||||
|
#
|
||||||
|
$e = {
|
||||||
|
'FILE' => 'foo.idl',
|
||||||
|
'NAME' => 'v',
|
||||||
|
'PROPERTIES' => {"ref" => 1},
|
||||||
|
'POINTERS' => 3,
|
||||||
|
'TYPE' => 'uint8',
|
||||||
|
'PARENT' => { TYPE => 'STRUCT' },
|
||||||
|
'LINE' => 42 };
|
||||||
|
|
||||||
|
is_deeply(GetElementLevelTable($e, "unique", 0), [
|
||||||
|
{
|
||||||
|
LEVEL_INDEX => 0,
|
||||||
|
IS_DEFERRED => 0,
|
||||||
|
TYPE => 'POINTER',
|
||||||
|
POINTER_TYPE => "ref",
|
||||||
|
POINTER_INDEX => 0,
|
||||||
|
LEVEL => 'EMBEDDED'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
LEVEL_INDEX => 1,
|
||||||
|
IS_DEFERRED => 1,
|
||||||
|
TYPE => 'POINTER',
|
||||||
|
POINTER_TYPE => "unique",
|
||||||
|
POINTER_INDEX => 1,
|
||||||
|
LEVEL => 'EMBEDDED'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
LEVEL_INDEX => 2,
|
||||||
|
IS_DEFERRED => 1,
|
||||||
|
TYPE => 'POINTER',
|
||||||
|
POINTER_TYPE => "unique",
|
||||||
|
POINTER_INDEX => 2,
|
||||||
|
LEVEL => 'EMBEDDED'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'IS_DEFERRED' => 1,
|
||||||
|
'LEVEL_INDEX' => 3,
|
||||||
|
'DATA_TYPE' => 'uint8',
|
||||||
|
'CONTAINS_DEFERRED' => 0,
|
||||||
|
'TYPE' => 'DATA',
|
||||||
|
'IS_SURROUNDING' => 0,
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
|
||||||
|
# Case 3 : ref pointers
|
||||||
|
#
|
||||||
|
$e = {
|
||||||
|
'FILE' => 'foo.idl',
|
||||||
|
'NAME' => 'v',
|
||||||
|
'PROPERTIES' => {"ref" => 1},
|
||||||
|
'POINTERS' => 3,
|
||||||
|
'TYPE' => 'uint8',
|
||||||
|
'PARENT' => { TYPE => 'STRUCT' },
|
||||||
|
'LINE' => 42 };
|
||||||
|
|
||||||
|
is_deeply(GetElementLevelTable($e, "ref", 0), [
|
||||||
|
{
|
||||||
|
LEVEL_INDEX => 0,
|
||||||
|
IS_DEFERRED => 0,
|
||||||
|
TYPE => 'POINTER',
|
||||||
|
POINTER_TYPE => "ref",
|
||||||
|
POINTER_INDEX => 0,
|
||||||
|
LEVEL => 'EMBEDDED'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
LEVEL_INDEX => 1,
|
||||||
|
IS_DEFERRED => 1,
|
||||||
|
TYPE => 'POINTER',
|
||||||
|
POINTER_TYPE => "ref",
|
||||||
|
POINTER_INDEX => 1,
|
||||||
|
LEVEL => 'EMBEDDED'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
LEVEL_INDEX => 2,
|
||||||
|
IS_DEFERRED => 1,
|
||||||
|
TYPE => 'POINTER',
|
||||||
|
POINTER_TYPE => "ref",
|
||||||
|
POINTER_INDEX => 2,
|
||||||
|
LEVEL => 'EMBEDDED'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'IS_DEFERRED' => 1,
|
||||||
|
'LEVEL_INDEX' => 3,
|
||||||
|
'DATA_TYPE' => 'uint8',
|
||||||
|
'CONTAINS_DEFERRED' => 0,
|
||||||
|
'TYPE' => 'DATA',
|
||||||
|
'IS_SURROUNDING' => 0,
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
|
||||||
|
# Case 4 : top-level ref pointers
|
||||||
|
#
|
||||||
|
$e = {
|
||||||
|
'FILE' => 'foo.idl',
|
||||||
|
'NAME' => 'v',
|
||||||
|
'PROPERTIES' => {"ref" => 1},
|
||||||
|
'POINTERS' => 1,
|
||||||
|
'TYPE' => 'uint8',
|
||||||
|
'PARENT' => { TYPE => 'FUNCTION' },
|
||||||
|
'LINE' => 42 };
|
||||||
|
|
||||||
|
is_deeply(GetElementLevelTable($e, "unique", 0), [
|
||||||
|
{
|
||||||
|
LEVEL_INDEX => 0,
|
||||||
|
IS_DEFERRED => 0,
|
||||||
|
TYPE => 'POINTER',
|
||||||
|
POINTER_TYPE => "ref",
|
||||||
|
POINTER_INDEX => 0,
|
||||||
|
LEVEL => 'TOP'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'IS_DEFERRED' => 0,
|
||||||
|
'LEVEL_INDEX' => 1,
|
||||||
|
'DATA_TYPE' => 'uint8',
|
||||||
|
'CONTAINS_DEFERRED' => 0,
|
||||||
|
'TYPE' => 'DATA',
|
||||||
|
'IS_SURROUNDING' => 0,
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
|
||||||
|
# Case 4 : top-level ref pointers, triple with pointer_default("unique")
|
||||||
|
#
|
||||||
|
$e = {
|
||||||
|
'FILE' => 'foo.idl',
|
||||||
|
'NAME' => 'v',
|
||||||
|
'PROPERTIES' => {"ref" => 1},
|
||||||
|
'POINTERS' => 3,
|
||||||
|
'TYPE' => 'uint8',
|
||||||
|
'PARENT' => { TYPE => 'FUNCTION' },
|
||||||
|
'LINE' => 42 };
|
||||||
|
|
||||||
|
is_deeply(GetElementLevelTable($e, "unique", 0), [
|
||||||
|
{
|
||||||
|
LEVEL_INDEX => 0,
|
||||||
|
IS_DEFERRED => 0,
|
||||||
|
TYPE => 'POINTER',
|
||||||
|
POINTER_TYPE => "ref",
|
||||||
|
POINTER_INDEX => 0,
|
||||||
|
LEVEL => 'TOP'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
LEVEL_INDEX => 1,
|
||||||
|
IS_DEFERRED => 0,
|
||||||
|
TYPE => 'POINTER',
|
||||||
|
POINTER_TYPE => "unique",
|
||||||
|
POINTER_INDEX => 1,
|
||||||
|
LEVEL => 'EMBEDDED'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
LEVEL_INDEX => 2,
|
||||||
|
IS_DEFERRED => 1,
|
||||||
|
TYPE => 'POINTER',
|
||||||
|
POINTER_TYPE => "unique",
|
||||||
|
POINTER_INDEX => 2,
|
||||||
|
LEVEL => 'EMBEDDED'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'IS_DEFERRED' => 1,
|
||||||
|
'LEVEL_INDEX' => 3,
|
||||||
|
'DATA_TYPE' => 'uint8',
|
||||||
|
'CONTAINS_DEFERRED' => 0,
|
||||||
|
'TYPE' => 'DATA',
|
||||||
|
'IS_SURROUNDING' => 0,
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
|
||||||
|
# Case 4 : top-level unique pointers, triple with pointer_default("unique")
|
||||||
|
#
|
||||||
|
$e = {
|
||||||
|
'FILE' => 'foo.idl',
|
||||||
|
'NAME' => 'v',
|
||||||
|
'PROPERTIES' => {"unique" => 1, "in" => 1},
|
||||||
|
'POINTERS' => 3,
|
||||||
|
'TYPE' => 'uint8',
|
||||||
|
'PARENT' => { TYPE => 'FUNCTION' },
|
||||||
|
'LINE' => 42 };
|
||||||
|
|
||||||
|
is_deeply(GetElementLevelTable($e, "unique", 0), [
|
||||||
|
{
|
||||||
|
LEVEL_INDEX => 0,
|
||||||
|
IS_DEFERRED => 0,
|
||||||
|
TYPE => 'POINTER',
|
||||||
|
POINTER_TYPE => "unique",
|
||||||
|
POINTER_INDEX => 0,
|
||||||
|
LEVEL => 'TOP'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
LEVEL_INDEX => 1,
|
||||||
|
IS_DEFERRED => 1,
|
||||||
|
TYPE => 'POINTER',
|
||||||
|
POINTER_TYPE => "unique",
|
||||||
|
POINTER_INDEX => 1,
|
||||||
|
LEVEL => 'EMBEDDED'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
LEVEL_INDEX => 2,
|
||||||
|
IS_DEFERRED => 1,
|
||||||
|
TYPE => 'POINTER',
|
||||||
|
POINTER_TYPE => "unique",
|
||||||
|
POINTER_INDEX => 2,
|
||||||
|
LEVEL => 'EMBEDDED'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'IS_DEFERRED' => 1,
|
||||||
|
'LEVEL_INDEX' => 3,
|
||||||
|
'DATA_TYPE' => 'uint8',
|
||||||
|
'CONTAINS_DEFERRED' => 0,
|
||||||
|
'TYPE' => 'DATA',
|
||||||
|
'IS_SURROUNDING' => 0,
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
|
||||||
|
# Case 4 : top-level unique pointers, triple with pointer_default("ref")
|
||||||
|
#
|
||||||
|
$e = {
|
||||||
|
'FILE' => 'foo.idl',
|
||||||
|
'NAME' => 'v',
|
||||||
|
'PROPERTIES' => {"unique" => 1, "in" => 1},
|
||||||
|
'POINTERS' => 3,
|
||||||
|
'TYPE' => 'uint8',
|
||||||
|
'PARENT' => { TYPE => 'FUNCTION' },
|
||||||
|
'LINE' => 42 };
|
||||||
|
|
||||||
|
is_deeply(GetElementLevelTable($e, "ref", 0), [
|
||||||
|
{
|
||||||
|
LEVEL_INDEX => 0,
|
||||||
|
IS_DEFERRED => 0,
|
||||||
|
TYPE => 'POINTER',
|
||||||
|
POINTER_TYPE => "unique",
|
||||||
|
POINTER_INDEX => 0,
|
||||||
|
LEVEL => 'TOP'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
LEVEL_INDEX => 1,
|
||||||
|
IS_DEFERRED => 1,
|
||||||
|
TYPE => 'POINTER',
|
||||||
|
POINTER_TYPE => "ref",
|
||||||
|
POINTER_INDEX => 1,
|
||||||
|
LEVEL => 'EMBEDDED'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
LEVEL_INDEX => 2,
|
||||||
|
IS_DEFERRED => 1,
|
||||||
|
TYPE => 'POINTER',
|
||||||
|
POINTER_TYPE => "ref",
|
||||||
|
POINTER_INDEX => 2,
|
||||||
|
LEVEL => 'EMBEDDED'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'IS_DEFERRED' => 1,
|
||||||
|
'LEVEL_INDEX' => 3,
|
||||||
|
'DATA_TYPE' => 'uint8',
|
||||||
|
'CONTAINS_DEFERRED' => 0,
|
||||||
|
'TYPE' => 'DATA',
|
||||||
|
'IS_SURROUNDING' => 0,
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
|
||||||
|
# Case 4 : top-level ref pointers, triple with pointer_default("ref")
|
||||||
|
#
|
||||||
|
$e = {
|
||||||
|
'FILE' => 'foo.idl',
|
||||||
|
'NAME' => 'v',
|
||||||
|
'PROPERTIES' => {"ref" => 1},
|
||||||
|
'POINTERS' => 3,
|
||||||
|
'TYPE' => 'uint8',
|
||||||
|
'PARENT' => { TYPE => 'FUNCTION' },
|
||||||
|
'LINE' => 42 };
|
||||||
|
|
||||||
|
is_deeply(GetElementLevelTable($e, "ref", 0), [
|
||||||
|
{
|
||||||
|
LEVEL_INDEX => 0,
|
||||||
|
IS_DEFERRED => 0,
|
||||||
|
TYPE => 'POINTER',
|
||||||
|
POINTER_TYPE => "ref",
|
||||||
|
POINTER_INDEX => 0,
|
||||||
|
LEVEL => 'TOP'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
LEVEL_INDEX => 1,
|
||||||
|
IS_DEFERRED => 0,
|
||||||
|
TYPE => 'POINTER',
|
||||||
|
POINTER_TYPE => "ref",
|
||||||
|
POINTER_INDEX => 1,
|
||||||
|
LEVEL => 'EMBEDDED'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
LEVEL_INDEX => 2,
|
||||||
|
IS_DEFERRED => 1,
|
||||||
|
TYPE => 'POINTER',
|
||||||
|
POINTER_TYPE => "ref",
|
||||||
|
POINTER_INDEX => 2,
|
||||||
|
LEVEL => 'EMBEDDED'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'IS_DEFERRED' => 1,
|
||||||
|
'LEVEL_INDEX' => 3,
|
||||||
|
'DATA_TYPE' => 'uint8',
|
||||||
|
'CONTAINS_DEFERRED' => 0,
|
||||||
|
'TYPE' => 'DATA',
|
||||||
|
'IS_SURROUNDING' => 0,
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
|
||||||
|
# representation_type
|
||||||
|
$e = {
|
||||||
|
'FILE' => 'foo.idl',
|
||||||
|
'NAME' => 'v',
|
||||||
|
'PROPERTIES' => { represent_as => "bar" },
|
||||||
|
'POINTERS' => 0,
|
||||||
|
'TYPE' => 'uint8',
|
||||||
|
'PARENT' => { TYPE => 'STRUCT' },
|
||||||
|
'LINE' => 42 };
|
||||||
|
|
||||||
|
$ne = ParseElement($e, undef, 0);
|
||||||
|
is($ne->{REPRESENTATION_TYPE}, "bar");
|
||||||
|
|
||||||
|
# representation_type
|
||||||
|
$e = {
|
||||||
|
'FILE' => 'foo.idl',
|
||||||
|
'NAME' => 'v',
|
||||||
|
'PROPERTIES' => { },
|
||||||
|
'POINTERS' => 0,
|
||||||
|
'TYPE' => 'uint8',
|
||||||
|
'PARENT' => { TYPE => 'STRUCT' },
|
||||||
|
'LINE' => 42 };
|
||||||
|
|
||||||
|
$ne = ParseElement($e, undef, 0);
|
||||||
|
is($ne->{REPRESENTATION_TYPE}, "uint8");
|
||||||
|
|
||||||
|
is(align_type("hyper"), 8);
|
||||||
|
is(align_type("double"), 8);
|
||||||
|
is(align_type("uint32"), 4);
|
||||||
|
is(align_type("uint16"), 2);
|
||||||
|
is(align_type("uint8"), 1);
|
||||||
|
is(align_type({ TYPE => "STRUCT", "NAME" => "bla",
|
||||||
|
ELEMENTS => [ { TYPE => "uint16" } ] }), 4);
|
||||||
|
is(align_type({ TYPE => "STRUCT",
|
||||||
|
ELEMENTS => [ { TYPE => "hyper" } ] }), 8);
|
||||||
|
is(align_type({ TYPE => "TYPEDEF", DATA => {
|
||||||
|
TYPE => "STRUCT",
|
||||||
|
ELEMENTS => [ { TYPE => "hyper" } ] }}), 8);
|
||||||
|
# typedef of struct without body
|
||||||
|
is(align_type({ TYPE => "TYPEDEF", DATA => {
|
||||||
|
TYPE => "STRUCT", ELEMENTS => undef }}), 4);
|
||||||
|
# struct without body
|
||||||
|
is(align_type({ TYPE => "STRUCT", ELEMENTS => undef }), 4);
|
||||||
|
# empty struct
|
||||||
|
is(align_type({ TYPE => "STRUCT", ELEMENTS => [] }), 1);
|
||||||
|
is(align_type({ TYPE => "STRUCT", "NAME" => "bla",
|
||||||
|
ELEMENTS => [ { TYPE => "uint8" } ] }), 4);
|
||||||
|
|
||||||
|
is(mapToScalar("someverymuchnotexistingtype"), undef);
|
||||||
|
is(mapToScalar("uint32"), "uint32");
|
||||||
|
is(mapToScalar({TYPE => "ENUM", PARENT => { PROPERTIES => { enum8bit => 1 } } }), "uint8");
|
||||||
|
is(mapToScalar({TYPE => "BITMAP", PROPERTIES => { bitmap64bit => 1 } }),
|
||||||
|
"hyper");
|
||||||
|
is(mapToScalar({TYPE => "TYPEDEF", DATA => {TYPE => "ENUM", PARENT => { PROPERTIES => { enum8bit => 1 } } }}), "uint8");
|
||||||
|
|
||||||
|
my $t;
|
||||||
|
$t = {
|
||||||
|
TYPE => "STRUCT",
|
||||||
|
NAME => "foo",
|
||||||
|
SURROUNDING_ELEMENT => undef,
|
||||||
|
ELEMENTS => undef,
|
||||||
|
PROPERTIES => undef,
|
||||||
|
ORIGINAL => {
|
||||||
|
TYPE => "STRUCT",
|
||||||
|
NAME => "foo"
|
||||||
|
},
|
||||||
|
ALIGN => undef
|
||||||
|
};
|
||||||
|
is_deeply(ParseType($t->{ORIGINAL}, "ref", 0), $t);
|
||||||
|
|
||||||
|
$t = {
|
||||||
|
TYPE => "UNION",
|
||||||
|
NAME => "foo",
|
||||||
|
SWITCH_TYPE => "uint32",
|
||||||
|
ELEMENTS => undef,
|
||||||
|
PROPERTIES => undef,
|
||||||
|
HAS_DEFAULT => 0,
|
||||||
|
IS_MS_UNION => 0,
|
||||||
|
ORIGINAL => {
|
||||||
|
TYPE => "UNION",
|
||||||
|
NAME => "foo"
|
||||||
|
},
|
||||||
|
ALIGN => undef
|
||||||
|
};
|
||||||
|
is_deeply(ParseType($t->{ORIGINAL}, "ref", 0), $t);
|
||||||
|
|
||||||
|
ok(not can_contain_deferred("uint32"));
|
||||||
|
ok(can_contain_deferred("some_unknown_type"));
|
||||||
|
ok(can_contain_deferred({ TYPE => "STRUCT",
|
||||||
|
ELEMENTS => [ { TYPE => "uint32", POINTERS => 40 } ]}));
|
||||||
|
ok(can_contain_deferred({ TYPE => "TYPEDEF",
|
||||||
|
DATA => { TYPE => "STRUCT",
|
||||||
|
ELEMENTS => [ { TYPE => "uint32", POINTERS => 40 } ]}}));
|
||||||
|
ok(not can_contain_deferred({ TYPE => "STRUCT",
|
||||||
|
ELEMENTS => [ { TYPE => "uint32" } ]}));
|
||||||
|
ok(not can_contain_deferred({ TYPE => "TYPEDEF",
|
||||||
|
DATA => { TYPE => "STRUCT",
|
||||||
|
ELEMENTS => [ { TYPE => "uint32" } ]}}));
|
||||||
|
ok(can_contain_deferred({ TYPE => "STRUCT",
|
||||||
|
ELEMENTS => [ { TYPE => "someunknowntype" } ]}));
|
||||||
|
# Make sure the elements for a enum without body aren't filled in
|
||||||
|
ok(not defined(ParseType({TYPE => "ENUM", NAME => "foo" }, "ref", 0)->{ELEMENTS}));
|
||||||
|
# Make sure the elements for a bitmap without body aren't filled in
|
||||||
|
ok(not defined(ParseType({TYPE => "BITMAP", NAME => "foo" }, "ref", 0)->{ELEMENTS}));
|
||||||
|
# Make sure the elements for a union without body aren't filled in
|
||||||
|
ok(not defined(ParseType({TYPE => "UNION", NAME => "foo" }, "ref", 0)->{ELEMENTS}));
|
143
tools/pidl/tests/ndr_align.pl
Executable file
143
tools/pidl/tests/ndr_align.pl
Executable file
|
@ -0,0 +1,143 @@
|
||||||
|
#!/usr/bin/perl
|
||||||
|
# NDR alignment tests
|
||||||
|
# (C) 2005 Jelmer Vernooij. Published under the GNU GPL
|
||||||
|
use strict;
|
||||||
|
|
||||||
|
use Test::More tests => 5 * 8;
|
||||||
|
use FindBin qw($RealBin);
|
||||||
|
use lib "$RealBin";
|
||||||
|
use Util qw(test_samba4_ndr);
|
||||||
|
|
||||||
|
test_samba4_ndr('align-uint8-uint16',
|
||||||
|
'
|
||||||
|
typedef [public] struct {
|
||||||
|
uint8 x;
|
||||||
|
uint16 y;
|
||||||
|
} bla;
|
||||||
|
',
|
||||||
|
'
|
||||||
|
struct ndr_push *ndr = ndr_push_init_ctx(NULL, NULL);
|
||||||
|
struct bla r;
|
||||||
|
uint8_t expected[] = { 0x0D, 0x00, 0xef, 0xbe };
|
||||||
|
DATA_BLOB expected_blob = { expected, 4 };
|
||||||
|
DATA_BLOB result_blob;
|
||||||
|
r.x = 13;
|
||||||
|
r.y = 0xbeef;
|
||||||
|
|
||||||
|
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_push_bla(ndr, NDR_SCALARS|NDR_BUFFERS, &r)))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
result_blob = ndr_push_blob(ndr);
|
||||||
|
|
||||||
|
if (data_blob_cmp(&result_blob, &expected_blob) != 0)
|
||||||
|
return 2;
|
||||||
|
');
|
||||||
|
|
||||||
|
test_samba4_ndr('align-uint8-uint32',
|
||||||
|
'
|
||||||
|
typedef [public] struct {
|
||||||
|
uint8 x;
|
||||||
|
uint32 y;
|
||||||
|
} bla;
|
||||||
|
',
|
||||||
|
'
|
||||||
|
struct ndr_push *ndr = ndr_push_init_ctx(NULL, NULL);
|
||||||
|
struct bla r;
|
||||||
|
uint8_t expected[] = { 0x0D, 0x00, 0x00, 0x00, 0xef, 0xbe, 0xef, 0xbe };
|
||||||
|
DATA_BLOB expected_blob = { expected, 8 };
|
||||||
|
DATA_BLOB result_blob;
|
||||||
|
r.x = 13;
|
||||||
|
r.y = 0xbeefbeef;
|
||||||
|
|
||||||
|
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_push_bla(ndr, NDR_SCALARS|NDR_BUFFERS, &r)))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
result_blob = ndr_push_blob(ndr);
|
||||||
|
|
||||||
|
if (data_blob_cmp(&result_blob, &expected_blob) != 0)
|
||||||
|
return 2;
|
||||||
|
');
|
||||||
|
|
||||||
|
|
||||||
|
test_samba4_ndr('align-uint8-hyper',
|
||||||
|
'
|
||||||
|
typedef [public] struct {
|
||||||
|
uint8 x;
|
||||||
|
hyper y;
|
||||||
|
} bla;
|
||||||
|
',
|
||||||
|
'
|
||||||
|
struct ndr_push *ndr = ndr_push_init_ctx(NULL, NULL);
|
||||||
|
struct bla r;
|
||||||
|
uint8_t expected[] = { 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0xef, 0xbe, 0xef, 0xbe, 0xef, 0xbe, 0xef, 0xbe };
|
||||||
|
DATA_BLOB expected_blob = { expected, 16 };
|
||||||
|
DATA_BLOB result_blob;
|
||||||
|
r.x = 13;
|
||||||
|
r.y = 0xbeefbeefbeefbeefLLU;
|
||||||
|
|
||||||
|
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_push_bla(ndr, NDR_SCALARS|NDR_BUFFERS, &r)))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
result_blob = ndr_push_blob(ndr);
|
||||||
|
|
||||||
|
if (data_blob_cmp(&result_blob, &expected_blob) != 0)
|
||||||
|
return 2;
|
||||||
|
');
|
||||||
|
|
||||||
|
test_samba4_ndr('noalignflag-uint8-uint16',
|
||||||
|
'
|
||||||
|
typedef [public] struct {
|
||||||
|
uint8 x;
|
||||||
|
uint16 y;
|
||||||
|
} bla;
|
||||||
|
',
|
||||||
|
'
|
||||||
|
struct ndr_push *ndr = ndr_push_init_ctx(NULL, NULL);
|
||||||
|
struct bla r;
|
||||||
|
uint8_t expected[] = { 0x0D, 0xef, 0xbe };
|
||||||
|
DATA_BLOB expected_blob = { expected, 3 };
|
||||||
|
DATA_BLOB result_blob;
|
||||||
|
ndr->flags |= LIBNDR_FLAG_NOALIGN;
|
||||||
|
|
||||||
|
r.x = 13;
|
||||||
|
r.y = 0xbeef;
|
||||||
|
|
||||||
|
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_push_bla(ndr, NDR_SCALARS|NDR_BUFFERS, &r)))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
result_blob = ndr_push_blob(ndr);
|
||||||
|
|
||||||
|
if (data_blob_cmp(&result_blob, &expected_blob) != 0)
|
||||||
|
return 2;
|
||||||
|
');
|
||||||
|
|
||||||
|
test_samba4_ndr('align-blob-align2',
|
||||||
|
'
|
||||||
|
typedef [public] struct {
|
||||||
|
uint8 x;
|
||||||
|
[flag(LIBNDR_FLAG_ALIGN2)] DATA_BLOB data;
|
||||||
|
uint8 y;
|
||||||
|
} blie;
|
||||||
|
',
|
||||||
|
'
|
||||||
|
struct ndr_push *ndr = ndr_push_init_ctx(NULL, NULL);
|
||||||
|
struct blie r;
|
||||||
|
uint8_t data[] = { 0x01, 0x02 };
|
||||||
|
uint8_t expected[] = { 0x0D, 0x00, 0x0E };
|
||||||
|
DATA_BLOB expected_blob = { expected, 3 };
|
||||||
|
DATA_BLOB result_blob;
|
||||||
|
|
||||||
|
r.x = 13;
|
||||||
|
r.y = 14;
|
||||||
|
r.data.data = data;
|
||||||
|
r.data.length = 2;
|
||||||
|
|
||||||
|
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_push_blie(ndr, NDR_SCALARS|NDR_BUFFERS, &r)))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
result_blob = ndr_push_blob(ndr);
|
||||||
|
|
||||||
|
if (data_blob_cmp(&result_blob, &expected_blob) != 0)
|
||||||
|
return 2;
|
||||||
|
');
|
118
tools/pidl/tests/ndr_alloc.pl
Executable file
118
tools/pidl/tests/ndr_alloc.pl
Executable file
|
@ -0,0 +1,118 @@
|
||||||
|
#!/usr/bin/perl
|
||||||
|
# NDR allocation tests
|
||||||
|
# (C) 2005 Jelmer Vernooij. Published under the GNU GPL
|
||||||
|
use strict;
|
||||||
|
|
||||||
|
use Test::More tests => 5 * 8;
|
||||||
|
use FindBin qw($RealBin);
|
||||||
|
use lib "$RealBin";
|
||||||
|
use Util qw(test_samba4_ndr);
|
||||||
|
|
||||||
|
# Check that an outgoing scalar pointer is allocated correctly
|
||||||
|
|
||||||
|
test_samba4_ndr("alloc-scalar",
|
||||||
|
'
|
||||||
|
typedef struct {
|
||||||
|
uint8 *x;
|
||||||
|
} bla;
|
||||||
|
|
||||||
|
[public] void TestAlloc([in] bla foo);
|
||||||
|
','
|
||||||
|
uint8_t data[] = { 0xde, 0xad, 0xbe, 0xef, 0x03 };
|
||||||
|
DATA_BLOB b = { data, 5 };
|
||||||
|
struct ndr_pull *ndr = ndr_pull_init_blob(&b, NULL, NULL);
|
||||||
|
struct TestAlloc r;
|
||||||
|
|
||||||
|
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_pull_TestAlloc(ndr, NDR_IN, &r)))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
if (r.in.foo.x == NULL)
|
||||||
|
return 2;
|
||||||
|
|
||||||
|
if (*r.in.foo.x != 0x03)
|
||||||
|
return 3;
|
||||||
|
'
|
||||||
|
);
|
||||||
|
|
||||||
|
# Check that an outgoing buffer pointer is allocated correctly
|
||||||
|
test_samba4_ndr("alloc-buffer",
|
||||||
|
'
|
||||||
|
typedef struct { uint8 data; } blie;
|
||||||
|
typedef struct { blie *x; } bla;
|
||||||
|
|
||||||
|
[public] void TestAlloc([in] bla foo);
|
||||||
|
','
|
||||||
|
uint8_t data[] = { 0xde, 0xad, 0xbe, 0xef, 0x03 };
|
||||||
|
DATA_BLOB b = { data, 5 };
|
||||||
|
struct ndr_pull *ndr = ndr_pull_init_blob(&b, NULL, NULL);
|
||||||
|
struct TestAlloc r;
|
||||||
|
|
||||||
|
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_pull_TestAlloc(ndr, NDR_IN, &r)))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
if (r.in.foo.x == NULL)
|
||||||
|
return 2;
|
||||||
|
|
||||||
|
if (r.in.foo.x->data != 0x03)
|
||||||
|
return 3;
|
||||||
|
'
|
||||||
|
);
|
||||||
|
|
||||||
|
# Check that ref pointers aren't allocated by default
|
||||||
|
test_samba4_ndr("ref-noalloc-null",
|
||||||
|
'
|
||||||
|
[public] void TestAlloc([in,ref] uint8 *t);
|
||||||
|
','
|
||||||
|
uint8_t data[] = { 0x03 };
|
||||||
|
DATA_BLOB b = { data, 1 };
|
||||||
|
struct ndr_pull *ndr = ndr_pull_init_blob(&b, NULL, NULL);
|
||||||
|
struct TestAlloc r;
|
||||||
|
r.in.t = NULL;
|
||||||
|
|
||||||
|
if (NDR_ERR_CODE_IS_SUCCESS(ndr_pull_TestAlloc(ndr, NDR_IN, &r)))
|
||||||
|
return 1;
|
||||||
|
'
|
||||||
|
);
|
||||||
|
|
||||||
|
# Check that ref pointers aren't allocated by default
|
||||||
|
test_samba4_ndr("ref-noalloc",
|
||||||
|
'
|
||||||
|
[public] void TestAlloc([in,ref] uint8 *t);
|
||||||
|
','
|
||||||
|
uint8_t data[] = { 0x03 };
|
||||||
|
DATA_BLOB b = { data, 1 };
|
||||||
|
struct ndr_pull *ndr = ndr_pull_init_blob(&b, NULL, NULL);
|
||||||
|
struct TestAlloc r;
|
||||||
|
uint8_t x;
|
||||||
|
r.in.t = &x;
|
||||||
|
|
||||||
|
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_pull_TestAlloc(ndr, NDR_IN, &r)))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
if (*r.in.t != 0x03)
|
||||||
|
return 2;
|
||||||
|
'
|
||||||
|
);
|
||||||
|
|
||||||
|
# Check that an outgoing ref pointer is allocated correctly
|
||||||
|
test_samba4_ndr("ref-alloc",
|
||||||
|
'
|
||||||
|
[public] void TestAlloc([in,ref] uint8 *t);
|
||||||
|
','
|
||||||
|
uint8_t data[] = { 0x03 };
|
||||||
|
DATA_BLOB b = { data, 1 };
|
||||||
|
struct ndr_pull *ndr = ndr_pull_init_blob(&b, NULL, NULL);
|
||||||
|
struct TestAlloc r;
|
||||||
|
ndr->flags |= LIBNDR_FLAG_REF_ALLOC;
|
||||||
|
r.in.t = NULL;
|
||||||
|
|
||||||
|
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_pull_TestAlloc(ndr, NDR_IN, &r)))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
if (r.in.t == NULL)
|
||||||
|
return 2;
|
||||||
|
|
||||||
|
if (*r.in.t != 0x03)
|
||||||
|
return 3;
|
||||||
|
'
|
||||||
|
);
|
37
tools/pidl/tests/ndr_array.pl
Executable file
37
tools/pidl/tests/ndr_array.pl
Executable file
|
@ -0,0 +1,37 @@
|
||||||
|
#!/usr/bin/perl
|
||||||
|
# Array testing
|
||||||
|
# (C) 2005 Jelmer Vernooij <jelmer@samba.org>
|
||||||
|
# Published under the GNU General Public License
|
||||||
|
use strict;
|
||||||
|
|
||||||
|
use Test::More tests => 8;
|
||||||
|
use FindBin qw($RealBin);
|
||||||
|
use lib "$RealBin";
|
||||||
|
use Util qw(test_samba4_ndr);
|
||||||
|
|
||||||
|
test_samba4_ndr(
|
||||||
|
'Fixed-Array',
|
||||||
|
|
||||||
|
'[public] void Test([in] uint8 x[10]);',
|
||||||
|
|
||||||
|
'
|
||||||
|
uint8_t data[] = {1,2,3,4,5,6,7,8,9,10};
|
||||||
|
int i;
|
||||||
|
DATA_BLOB b;
|
||||||
|
struct ndr_pull *ndr;
|
||||||
|
struct Test r;
|
||||||
|
|
||||||
|
b.data = data;
|
||||||
|
b.length = 10;
|
||||||
|
ndr = ndr_pull_init_blob(&b, mem_ctx, NULL);
|
||||||
|
|
||||||
|
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_pull_Test(ndr, NDR_IN, &r)))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
if (ndr->offset != 10)
|
||||||
|
return 2;
|
||||||
|
|
||||||
|
for (i = 0; i < 10; i++) {
|
||||||
|
if (r.in.x[i] != i+1) return 3;
|
||||||
|
}
|
||||||
|
');
|
21
tools/pidl/tests/ndr_compat.pl
Executable file
21
tools/pidl/tests/ndr_compat.pl
Executable file
|
@ -0,0 +1,21 @@
|
||||||
|
#!/usr/bin/perl
|
||||||
|
# (C) 2007 Jelmer Vernooij <jelmer@samba.org>
|
||||||
|
# Published under the GNU General Public License
|
||||||
|
use strict;
|
||||||
|
|
||||||
|
use Test::More tests => 2;
|
||||||
|
use FindBin qw($RealBin);
|
||||||
|
use lib "$RealBin";
|
||||||
|
use Util;
|
||||||
|
use Parse::Pidl;
|
||||||
|
use Parse::Pidl::IDL;
|
||||||
|
|
||||||
|
sub parse_idl($)
|
||||||
|
{
|
||||||
|
my $idl = shift;
|
||||||
|
my $pidl = Parse::Pidl::IDL::parse_string("interface echo { $idl }; ", "nofile");
|
||||||
|
Parse::Pidl::NDR::Parse($pidl);
|
||||||
|
}
|
||||||
|
|
||||||
|
test_warnings("", sub {parse_idl("void x();"); });
|
||||||
|
test_warnings("nofile:0: top-level [out] pointer `x' is not a [ref] pointer\n", sub {parse_idl("void x([out,unique] int *x);"); });
|
26
tools/pidl/tests/ndr_deprecations.pl
Executable file
26
tools/pidl/tests/ndr_deprecations.pl
Executable file
|
@ -0,0 +1,26 @@
|
||||||
|
#!/usr/bin/perl
|
||||||
|
# (C) 2007 Jelmer Vernooij <jelmer@samba.org>
|
||||||
|
# Published under the GNU General Public License
|
||||||
|
use strict;
|
||||||
|
use warnings;
|
||||||
|
|
||||||
|
use Test::More tests => 1;
|
||||||
|
use FindBin qw($RealBin);
|
||||||
|
use lib "$RealBin";
|
||||||
|
use Util;
|
||||||
|
use Parse::Pidl::Util qw(MyDumper);
|
||||||
|
use Parse::Pidl::NDR qw(ValidElement);
|
||||||
|
|
||||||
|
# Case 1
|
||||||
|
|
||||||
|
my $e = {
|
||||||
|
'FILE' => 'foo.idl',
|
||||||
|
'NAME' => 'v',
|
||||||
|
'PROPERTIES' => {"subcontext" => 1},
|
||||||
|
'POINTERS' => 0,
|
||||||
|
'TYPE' => 'uint8',
|
||||||
|
'PARENT' => { TYPE => 'STRUCT' },
|
||||||
|
'LINE' => 42 };
|
||||||
|
|
||||||
|
test_warnings("foo.idl:42: subcontext() is deprecated. Use represent_as() or transmit_as() instead\n",
|
||||||
|
sub { ValidElement($e); });
|
44
tools/pidl/tests/ndr_fullptr.pl
Executable file
44
tools/pidl/tests/ndr_fullptr.pl
Executable file
|
@ -0,0 +1,44 @@
|
||||||
|
#!/usr/bin/perl
|
||||||
|
# Simple tests for unique pointers
|
||||||
|
# (C) 2006 Jelmer Vernooij <jelmer@samba.org>.
|
||||||
|
# Published under the GNU General Public License.
|
||||||
|
use strict;
|
||||||
|
|
||||||
|
use Test::More tests => 1 * 8;
|
||||||
|
use FindBin qw($RealBin);
|
||||||
|
use lib "$RealBin";
|
||||||
|
use Util qw(test_samba4_ndr);
|
||||||
|
|
||||||
|
SKIP: {
|
||||||
|
skip "full pointers not supported yet", 8;
|
||||||
|
|
||||||
|
test_samba4_ndr("fullptr-push-dup",
|
||||||
|
'
|
||||||
|
[public] uint16 echo_TestFull([in,ptr] uint32 *x, [in,ptr] uint32 *y);
|
||||||
|
',
|
||||||
|
'
|
||||||
|
struct ndr_push *ndr = ndr_push_init_ctx(NULL, NULL);
|
||||||
|
uint32_t v = 13;
|
||||||
|
struct echo_TestFull r;
|
||||||
|
r.in.x = &v;
|
||||||
|
r.in.y = &v;
|
||||||
|
|
||||||
|
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_push_echo_TestFull(ndr, NDR_IN, &r))) {
|
||||||
|
fprintf(stderr, "push failed\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ndr->offset != 12) {
|
||||||
|
fprintf(stderr, "Offset(%d) != 12\n", ndr->offset);
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ndr->data[0] != ndr->data[8] ||
|
||||||
|
ndr->data[1] != ndr->data[9] ||
|
||||||
|
ndr->data[2] != ndr->data[10] ||
|
||||||
|
ndr->data[3] != ndr->data[11]) {
|
||||||
|
fprintf(stderr, "Data incorrect\n");
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
');
|
||||||
|
}
|
526
tools/pidl/tests/ndr_refptr.pl
Executable file
526
tools/pidl/tests/ndr_refptr.pl
Executable file
|
@ -0,0 +1,526 @@
|
||||||
|
#!/usr/bin/perl
|
||||||
|
# Simple tests for pidl's handling of ref pointers, based
|
||||||
|
# on tridge's ref_notes.txt
|
||||||
|
# (C) 2005 Jelmer Vernooij <jelmer@samba.org>.
|
||||||
|
# Published under the GNU General Public License.
|
||||||
|
use strict;
|
||||||
|
|
||||||
|
use Test::More tests => 22 * 8;
|
||||||
|
use FindBin qw($RealBin);
|
||||||
|
use lib "$RealBin";
|
||||||
|
use Util qw(test_samba4_ndr);
|
||||||
|
|
||||||
|
test_samba4_ndr("noptr-push",
|
||||||
|
' typedef struct {
|
||||||
|
uint16 x;
|
||||||
|
} xstruct;
|
||||||
|
|
||||||
|
[public] uint16 echo_TestRef([in] xstruct foo);
|
||||||
|
',
|
||||||
|
'
|
||||||
|
struct ndr_push *ndr = ndr_push_init_ctx(NULL, NULL);
|
||||||
|
uint16_t v = 13;
|
||||||
|
struct echo_TestRef r;
|
||||||
|
r.in.foo.x = v;
|
||||||
|
|
||||||
|
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_push_echo_TestRef(ndr, NDR_IN, &r))) {
|
||||||
|
fprintf(stderr, "push failed\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ndr->offset != 2) {
|
||||||
|
fprintf(stderr, "Offset(%d) != 2\n", ndr->offset);
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ndr->data[0] != 13 || ndr->data[1] != 0) {
|
||||||
|
fprintf(stderr, "Data incorrect\n");
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
');
|
||||||
|
|
||||||
|
test_samba4_ndr("ptr-embedded-push",
|
||||||
|
' typedef struct {
|
||||||
|
uint16 *x;
|
||||||
|
} xstruct;
|
||||||
|
|
||||||
|
[public] uint16 echo_TestRef([in] xstruct foo);
|
||||||
|
',
|
||||||
|
'
|
||||||
|
uint16_t v = 13;
|
||||||
|
struct ndr_push *ndr = ndr_push_init_ctx(NULL, NULL);
|
||||||
|
struct echo_TestRef r;
|
||||||
|
r.in.foo.x = &v;
|
||||||
|
|
||||||
|
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_push_echo_TestRef(ndr, NDR_IN, &r)))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
if (ndr->offset != 6)
|
||||||
|
return 2;
|
||||||
|
|
||||||
|
if (ndr->data[0] == 0 && ndr->data[1] == 0 &&
|
||||||
|
ndr->data[2] == 0 && ndr->data[3] == 0)
|
||||||
|
return 3;
|
||||||
|
|
||||||
|
if (ndr->data[4] != 13 || ndr->data[5] != 0)
|
||||||
|
return 4;
|
||||||
|
');
|
||||||
|
|
||||||
|
test_samba4_ndr("ptr-embedded-push-null",
|
||||||
|
' typedef struct {
|
||||||
|
uint16 *x;
|
||||||
|
} xstruct;
|
||||||
|
|
||||||
|
[public] uint16 echo_TestRef([in] xstruct foo);
|
||||||
|
',
|
||||||
|
'
|
||||||
|
struct ndr_push *ndr = ndr_push_init_ctx(NULL, NULL);
|
||||||
|
struct echo_TestRef r;
|
||||||
|
r.in.foo.x = NULL;
|
||||||
|
|
||||||
|
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_push_echo_TestRef(ndr, NDR_IN, &r)))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
if (ndr->offset != 4)
|
||||||
|
return 2;
|
||||||
|
|
||||||
|
if (ndr->data[0] != 0 || ndr->data[1] != 0 ||
|
||||||
|
ndr->data[2] != 0 || ndr->data[3] != 0)
|
||||||
|
return 3;
|
||||||
|
');
|
||||||
|
|
||||||
|
test_samba4_ndr("refptr-embedded-push",
|
||||||
|
'
|
||||||
|
typedef struct {
|
||||||
|
[ref] uint16 *x;
|
||||||
|
} xstruct;
|
||||||
|
|
||||||
|
[public] uint16 echo_TestRef([in] xstruct foo);
|
||||||
|
',
|
||||||
|
'
|
||||||
|
uint16_t v = 13;
|
||||||
|
struct ndr_push *ndr = ndr_push_init_ctx(NULL, NULL);
|
||||||
|
struct echo_TestRef r;
|
||||||
|
r.in.foo.x = &v;
|
||||||
|
|
||||||
|
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_push_echo_TestRef(ndr, NDR_IN, &r)))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
if (ndr->offset != 6)
|
||||||
|
return 2;
|
||||||
|
|
||||||
|
if (ndr->data[0] == 0 && ndr->data[1] == 0 &&
|
||||||
|
ndr->data[2] == 0 && ndr->data[3] == 0)
|
||||||
|
return 3;
|
||||||
|
|
||||||
|
if (ndr->data[4] != 13 || ndr->data[5] != 0)
|
||||||
|
return 4;
|
||||||
|
');
|
||||||
|
|
||||||
|
test_samba4_ndr("refptr-embedded-push-null",
|
||||||
|
'
|
||||||
|
typedef struct {
|
||||||
|
[ref] uint16 *x;
|
||||||
|
} xstruct;
|
||||||
|
|
||||||
|
[public] uint16 echo_TestRef([in] xstruct foo);
|
||||||
|
',
|
||||||
|
'
|
||||||
|
struct ndr_push *ndr = ndr_push_init_ctx(NULL, NULL);
|
||||||
|
struct echo_TestRef r;
|
||||||
|
r.in.foo.x = NULL;
|
||||||
|
|
||||||
|
if (NDR_ERR_CODE_IS_SUCCESS(ndr_push_echo_TestRef(ndr, NDR_IN, &r)))
|
||||||
|
return 1;
|
||||||
|
/* Windows gives [client runtime error 0x6f4] */
|
||||||
|
');
|
||||||
|
|
||||||
|
test_samba4_ndr("ptr-top-push",
|
||||||
|
'
|
||||||
|
typedef struct {
|
||||||
|
uint16 x;
|
||||||
|
} xstruct;
|
||||||
|
|
||||||
|
[public] uint16 echo_TestRef([in] xstruct *foo);
|
||||||
|
',
|
||||||
|
'
|
||||||
|
struct ndr_push *ndr = ndr_push_init_ctx(NULL, NULL);
|
||||||
|
struct echo_TestRef r;
|
||||||
|
struct xstruct s;
|
||||||
|
s.x = 13;
|
||||||
|
r.in.foo = &s;
|
||||||
|
|
||||||
|
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_push_echo_TestRef(ndr, NDR_IN, &r)))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
if (ndr->offset != 2)
|
||||||
|
return 2;
|
||||||
|
|
||||||
|
if (ndr->data[0] != 13 || ndr->data[1] != 0)
|
||||||
|
return 3;
|
||||||
|
');
|
||||||
|
|
||||||
|
test_samba4_ndr("ptr-top-push-null",
|
||||||
|
'
|
||||||
|
typedef struct {
|
||||||
|
uint16 x;
|
||||||
|
} xstruct;
|
||||||
|
|
||||||
|
[public] uint16 echo_TestRef([in] xstruct *foo);
|
||||||
|
',
|
||||||
|
'
|
||||||
|
struct ndr_push *ndr = ndr_push_init_ctx(NULL, NULL);
|
||||||
|
struct echo_TestRef r;
|
||||||
|
r.in.foo = NULL;
|
||||||
|
|
||||||
|
if (NDR_ERR_CODE_IS_SUCCESS(ndr_push_echo_TestRef(ndr, NDR_IN, &r)))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
/* Windows gives [client runtime error 0x6f4] */
|
||||||
|
');
|
||||||
|
|
||||||
|
|
||||||
|
test_samba4_ndr("refptr-top-push",
|
||||||
|
'
|
||||||
|
typedef struct {
|
||||||
|
uint16 x;
|
||||||
|
} xstruct;
|
||||||
|
|
||||||
|
[public] uint16 echo_TestRef([in,ref] xstruct *foo);
|
||||||
|
',
|
||||||
|
'
|
||||||
|
struct ndr_push *ndr = ndr_push_init_ctx(NULL, NULL);
|
||||||
|
struct echo_TestRef r;
|
||||||
|
struct xstruct s;
|
||||||
|
s.x = 13;
|
||||||
|
r.in.foo = &s;
|
||||||
|
|
||||||
|
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_push_echo_TestRef(ndr, NDR_IN, &r)))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
if (ndr->offset != 2)
|
||||||
|
return 2;
|
||||||
|
|
||||||
|
if (ndr->data[0] != 13 || ndr->data[1] != 0)
|
||||||
|
return 3;
|
||||||
|
');
|
||||||
|
|
||||||
|
test_samba4_ndr("refptr-top-push-null",
|
||||||
|
'
|
||||||
|
typedef struct {
|
||||||
|
uint16 x;
|
||||||
|
} xstruct;
|
||||||
|
|
||||||
|
[public] uint16 echo_TestRef([in,ref] xstruct *foo);
|
||||||
|
',
|
||||||
|
'
|
||||||
|
struct ndr_push *ndr = ndr_push_init_ctx(NULL, NULL);
|
||||||
|
struct echo_TestRef r;
|
||||||
|
r.in.foo = NULL;
|
||||||
|
|
||||||
|
if (NDR_ERR_CODE_IS_SUCCESS(ndr_push_echo_TestRef(ndr, NDR_IN, &r)))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
/* Windows gives [client runtime error 0x6f4] */
|
||||||
|
');
|
||||||
|
|
||||||
|
|
||||||
|
test_samba4_ndr("uniqueptr-top-push",
|
||||||
|
' typedef struct {
|
||||||
|
uint16 x;
|
||||||
|
} xstruct;
|
||||||
|
|
||||||
|
[public] uint16 echo_TestRef([in,unique] xstruct *foo);
|
||||||
|
',
|
||||||
|
'
|
||||||
|
struct ndr_push *ndr = ndr_push_init_ctx(NULL, NULL);
|
||||||
|
struct echo_TestRef r;
|
||||||
|
struct xstruct s;
|
||||||
|
s.x = 13;
|
||||||
|
r.in.foo = &s;
|
||||||
|
|
||||||
|
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_push_echo_TestRef(ndr, NDR_IN, &r)))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
if (ndr->offset != 6)
|
||||||
|
return 2;
|
||||||
|
|
||||||
|
if (ndr->data[0] == 0 && ndr->data[1] == 0 &&
|
||||||
|
ndr->data[2] == 0 && ndr->data[3] == 0)
|
||||||
|
return 3;
|
||||||
|
|
||||||
|
if (ndr->data[4] != 13 || ndr->data[5] != 0)
|
||||||
|
return 4;
|
||||||
|
');
|
||||||
|
|
||||||
|
test_samba4_ndr("uniqueptr-top-push-null",
|
||||||
|
' typedef struct {
|
||||||
|
uint16 x;
|
||||||
|
} xstruct;
|
||||||
|
|
||||||
|
[public] uint16 echo_TestRef([in,unique] xstruct *foo);
|
||||||
|
',
|
||||||
|
'
|
||||||
|
struct ndr_push *ndr = ndr_push_init_ctx(NULL, NULL);
|
||||||
|
struct echo_TestRef r;
|
||||||
|
r.in.foo = NULL;
|
||||||
|
|
||||||
|
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_push_echo_TestRef(ndr, NDR_IN, &r)))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
if (ndr->offset != 4)
|
||||||
|
return 2;
|
||||||
|
|
||||||
|
if (ndr->data[0] != 0 || ndr->data[1] != 0 ||
|
||||||
|
ndr->data[2] != 0 || ndr->data[3] != 0)
|
||||||
|
return 3;
|
||||||
|
');
|
||||||
|
|
||||||
|
|
||||||
|
test_samba4_ndr("ptr-top-out-pull",
|
||||||
|
'
|
||||||
|
typedef struct {
|
||||||
|
uint16 x;
|
||||||
|
} xstruct;
|
||||||
|
|
||||||
|
[public] void echo_TestRef([out] xstruct *foo);
|
||||||
|
',
|
||||||
|
'
|
||||||
|
uint8_t data[] = { 0x0D, 0x00 };
|
||||||
|
DATA_BLOB b = { data, 2 };
|
||||||
|
struct ndr_pull *ndr = ndr_pull_init_blob(&b, NULL, NULL);
|
||||||
|
struct xstruct s;
|
||||||
|
struct echo_TestRef r;
|
||||||
|
|
||||||
|
r.out.foo = &s;
|
||||||
|
|
||||||
|
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_pull_echo_TestRef(ndr, NDR_OUT, &r)))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
if (!r.out.foo)
|
||||||
|
return 2;
|
||||||
|
|
||||||
|
if (r.out.foo->x != 13)
|
||||||
|
return 3;
|
||||||
|
');
|
||||||
|
|
||||||
|
test_samba4_ndr("ptr-top-out-pull-null",
|
||||||
|
'
|
||||||
|
typedef struct {
|
||||||
|
uint16 x;
|
||||||
|
} xstruct;
|
||||||
|
|
||||||
|
[public] void echo_TestRef([out] xstruct *foo);
|
||||||
|
',
|
||||||
|
'
|
||||||
|
uint8_t data[] = { 0x0D, 0x00 };
|
||||||
|
DATA_BLOB b = { data, 2 };
|
||||||
|
struct ndr_pull *ndr = ndr_pull_init_blob(&b, NULL, NULL);
|
||||||
|
struct echo_TestRef r;
|
||||||
|
|
||||||
|
r.out.foo = NULL;
|
||||||
|
|
||||||
|
if (NDR_ERR_CODE_IS_SUCCESS(ndr_pull_echo_TestRef(ndr, NDR_OUT, &r)))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
/* Windows gives [client runtime error 0x6f4] */
|
||||||
|
');
|
||||||
|
|
||||||
|
|
||||||
|
test_samba4_ndr("refptr-top-out-pull",
|
||||||
|
'
|
||||||
|
typedef struct {
|
||||||
|
uint16 x;
|
||||||
|
} xstruct;
|
||||||
|
|
||||||
|
[public] void echo_TestRef([out,ref] xstruct *foo);
|
||||||
|
',
|
||||||
|
'
|
||||||
|
uint8_t data[] = { 0x0D, 0x00 };
|
||||||
|
DATA_BLOB b = { data, 2 };
|
||||||
|
struct ndr_pull *ndr = ndr_pull_init_blob(&b, NULL, NULL);
|
||||||
|
struct xstruct s;
|
||||||
|
struct echo_TestRef r;
|
||||||
|
|
||||||
|
r.out.foo = &s;
|
||||||
|
|
||||||
|
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_pull_echo_TestRef(ndr, NDR_OUT, &r)))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
if (!r.out.foo)
|
||||||
|
return 2;
|
||||||
|
|
||||||
|
if (r.out.foo->x != 13)
|
||||||
|
return 3;
|
||||||
|
');
|
||||||
|
|
||||||
|
test_samba4_ndr("refptr-top-out-pull-null",
|
||||||
|
'
|
||||||
|
typedef struct {
|
||||||
|
uint16 x;
|
||||||
|
} xstruct;
|
||||||
|
|
||||||
|
[public] void echo_TestRef([out,ref] xstruct *foo);
|
||||||
|
',
|
||||||
|
'
|
||||||
|
uint8_t data[] = { 0x0D, 0x00 };
|
||||||
|
DATA_BLOB b = { data, 2 };
|
||||||
|
struct ndr_pull *ndr = ndr_pull_init_blob(&b, NULL, NULL);
|
||||||
|
struct echo_TestRef r;
|
||||||
|
|
||||||
|
r.out.foo = NULL;
|
||||||
|
|
||||||
|
if (NDR_ERR_CODE_IS_SUCCESS(ndr_pull_echo_TestRef(ndr, NDR_OUT, &r)))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
/* Windows gives [client runtime error 0x6f4] */
|
||||||
|
');
|
||||||
|
|
||||||
|
|
||||||
|
test_samba4_ndr("ptr-top-push-double",
|
||||||
|
'
|
||||||
|
[public] void echo_TestRef([in] uint16 **foo);
|
||||||
|
',
|
||||||
|
' struct ndr_push *ndr = ndr_push_init_ctx(NULL, NULL);
|
||||||
|
struct echo_TestRef r;
|
||||||
|
uint16_t v = 13;
|
||||||
|
uint16_t *pv = &v;
|
||||||
|
r.in.foo = &pv;
|
||||||
|
|
||||||
|
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_push_echo_TestRef(ndr, NDR_IN, &r)))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
if (ndr->offset != 6)
|
||||||
|
return 2;
|
||||||
|
|
||||||
|
if (ndr->data[0] == 0 && ndr->data[1] == 0 &&
|
||||||
|
ndr->data[2] == 0 && ndr->data[3] == 0)
|
||||||
|
return 3;
|
||||||
|
|
||||||
|
if (ndr->data[4] != 0x0D || ndr->data[5] != 0x00)
|
||||||
|
return 4;
|
||||||
|
');
|
||||||
|
|
||||||
|
SKIP: {
|
||||||
|
skip "ptr-top-push-double-sndnull is known to fail", 8;
|
||||||
|
|
||||||
|
test_samba4_ndr("ptr-top-push-double-sndnull",
|
||||||
|
'
|
||||||
|
[public] void echo_TestRef([in] uint16 **foo);
|
||||||
|
',
|
||||||
|
' struct ndr_push *ndr = ndr_push_init_ctx(NULL, NULL);
|
||||||
|
struct echo_TestRef r;
|
||||||
|
uint16_t *pv = NULL;
|
||||||
|
r.in.foo = &pv;
|
||||||
|
|
||||||
|
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_push_echo_TestRef(ndr, NDR_IN, &r)))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
if (ndr->offset != 4)
|
||||||
|
return 2;
|
||||||
|
|
||||||
|
if (ndr->data[0] != 0 || ndr->data[1] != 0 ||
|
||||||
|
ndr->data[2] != 0 || ndr->data[3] != 0)
|
||||||
|
return 3;
|
||||||
|
');
|
||||||
|
}
|
||||||
|
|
||||||
|
test_samba4_ndr("ptr-top-push-double-fstnull",
|
||||||
|
'
|
||||||
|
[public] void echo_TestRef([in] uint16 **foo);
|
||||||
|
',
|
||||||
|
' struct ndr_push *ndr = ndr_push_init_ctx(NULL, NULL);
|
||||||
|
struct echo_TestRef r;
|
||||||
|
r.in.foo = NULL;
|
||||||
|
|
||||||
|
if (NDR_ERR_CODE_IS_SUCCESS(ndr_push_echo_TestRef(ndr, NDR_IN, &r)))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
/* Windows gives [client runtime error 0x6f4] */
|
||||||
|
|
||||||
|
');
|
||||||
|
|
||||||
|
|
||||||
|
test_samba4_ndr("refptr-top-push-double",
|
||||||
|
'
|
||||||
|
[public] void echo_TestRef([in,ref] uint16 **foo);
|
||||||
|
',
|
||||||
|
' struct ndr_push *ndr = ndr_push_init_ctx(NULL, NULL);
|
||||||
|
struct echo_TestRef r;
|
||||||
|
uint16_t v = 13;
|
||||||
|
uint16_t *pv = &v;
|
||||||
|
r.in.foo = &pv;
|
||||||
|
|
||||||
|
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_push_echo_TestRef(ndr, NDR_IN, &r)))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
if (ndr->offset != 6)
|
||||||
|
return 2;
|
||||||
|
|
||||||
|
if (ndr->data[0] == 0 && ndr->data[1] == 0 &&
|
||||||
|
ndr->data[2] == 0 && ndr->data[3] == 0)
|
||||||
|
return 3;
|
||||||
|
|
||||||
|
if (ndr->data[4] != 0x0D || ndr->data[5] != 0x00)
|
||||||
|
return 4;
|
||||||
|
');
|
||||||
|
|
||||||
|
SKIP: {
|
||||||
|
|
||||||
|
skip "refptr-top-push-double-sndnull is known to fail", 8;
|
||||||
|
|
||||||
|
test_samba4_ndr("refptr-top-push-double-sndnull",
|
||||||
|
'
|
||||||
|
[public] void echo_TestRef([in,ref] uint16 **foo);
|
||||||
|
',
|
||||||
|
' struct ndr_push *ndr = ndr_push_init_ctx(NULL, NULL);
|
||||||
|
struct echo_TestRef r;
|
||||||
|
uint16_t *pv = NULL;
|
||||||
|
r.in.foo = &pv;
|
||||||
|
|
||||||
|
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_push_echo_TestRef(ndr, NDR_IN, &r)))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
if (ndr->offset != 4)
|
||||||
|
return 2;
|
||||||
|
|
||||||
|
if (ndr->data[0] != 0 || ndr->data[1] != 0 ||
|
||||||
|
ndr->data[2] != 0 || ndr->data[3] != 0)
|
||||||
|
return 3;
|
||||||
|
');
|
||||||
|
}
|
||||||
|
|
||||||
|
test_samba4_ndr("refptr-top-push-double-fstnull",
|
||||||
|
'
|
||||||
|
[public] void echo_TestRef([in,ref] uint16 **foo);
|
||||||
|
',
|
||||||
|
' struct ndr_push *ndr = ndr_push_init_ctx(NULL, NULL);
|
||||||
|
struct echo_TestRef r;
|
||||||
|
r.in.foo = NULL;
|
||||||
|
|
||||||
|
if (NDR_ERR_CODE_IS_SUCCESS(ndr_push_echo_TestRef(ndr, NDR_IN, &r)))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
/* Windows gives [client runtime error 0x6f4] */
|
||||||
|
|
||||||
|
');
|
||||||
|
|
||||||
|
SKIP: {
|
||||||
|
skip "ignore-ptrs are not supported yet", 8;
|
||||||
|
test_samba4_ndr("ignore-ptr",
|
||||||
|
'
|
||||||
|
[public] void echo_TestRef([in,ignore] uint16 *foo, [in] uint16 *bar);
|
||||||
|
',
|
||||||
|
' struct ndr_push *ndr = ndr_push_init_ctx(NULL, NULL);
|
||||||
|
struct echo_TestRef r;
|
||||||
|
uint16_t v = 10;
|
||||||
|
r.in.foo = &v;
|
||||||
|
r.in.bar = &v;
|
||||||
|
|
||||||
|
if (NDR_ERR_CODE_IS_SUCCESS(ndr_push_echo_TestRef(ndr, NDR_IN, &r)))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
if (ndr->offset != 4)
|
||||||
|
return 2;
|
||||||
|
');
|
||||||
|
}
|
71
tools/pidl/tests/ndr_represent.pl
Executable file
71
tools/pidl/tests/ndr_represent.pl
Executable file
|
@ -0,0 +1,71 @@
|
||||||
|
#!/usr/bin/perl
|
||||||
|
# NDR represent_as() / transmit_as() tests
|
||||||
|
# (C) 2006 Jelmer Vernooij. Published under the GNU GPL
|
||||||
|
use strict;
|
||||||
|
|
||||||
|
use Test::More tests => 2 * 8;
|
||||||
|
use FindBin qw($RealBin);
|
||||||
|
use lib "$RealBin";
|
||||||
|
use Util qw(test_samba4_ndr);
|
||||||
|
|
||||||
|
test_samba4_ndr('represent_as-simple',
|
||||||
|
'
|
||||||
|
void bla([in,represent_as(uint32)] uint8 x);
|
||||||
|
',
|
||||||
|
'
|
||||||
|
uint8_t expected[] = { 0x0D };
|
||||||
|
DATA_BLOB in_blob = { expected, 1 };
|
||||||
|
struct ndr_pull *ndr = ndr_pull_init_blob(&in_blob, NULL, NULL);
|
||||||
|
struct bla r;
|
||||||
|
|
||||||
|
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_pull_bla(ndr, NDR_SCALARS|NDR_BUFFERS, &r)))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
if (r.in.x != 13)
|
||||||
|
return 2;
|
||||||
|
',
|
||||||
|
'
|
||||||
|
enum ndr_err_code ndr_uint8_to_uint32(uint8_t from, uint32_t *to)
|
||||||
|
{
|
||||||
|
*to = from;
|
||||||
|
return NDR_ERR_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum ndr_err_code ndr_uint32_to_uint8(uint32_t from, uint8_t *to)
|
||||||
|
{
|
||||||
|
*to = from;
|
||||||
|
return NDR_ERR_SUCCESS;
|
||||||
|
}
|
||||||
|
'
|
||||||
|
);
|
||||||
|
|
||||||
|
test_samba4_ndr('transmit_as-simple',
|
||||||
|
'
|
||||||
|
void bla([in,transmit_as(uint32)] uint8 x);
|
||||||
|
',
|
||||||
|
'
|
||||||
|
uint8_t expected[] = { 0x0D };
|
||||||
|
DATA_BLOB in_blob = { expected, 1 };
|
||||||
|
struct ndr_pull *ndr = ndr_pull_init_blob(&in_blob, NULL, NULL);
|
||||||
|
struct bla r;
|
||||||
|
|
||||||
|
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_pull_bla(ndr, NDR_SCALARS|NDR_BUFFERS, &r)))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
if (r.in.x != 13)
|
||||||
|
return 2;
|
||||||
|
',
|
||||||
|
'
|
||||||
|
enum ndr_err_code ndr_uint8_to_uint32(uint8_t from, uint32_t *to)
|
||||||
|
{
|
||||||
|
*to = from;
|
||||||
|
return NDR_ERR_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum ndr_err_code ndr_uint32_to_uint8(uint32_t from, uint8_t *to)
|
||||||
|
{
|
||||||
|
*to = from;
|
||||||
|
return NDR_ERR_SUCCESS;
|
||||||
|
}
|
||||||
|
'
|
||||||
|
);
|
28
tools/pidl/tests/ndr_simple.pl
Executable file
28
tools/pidl/tests/ndr_simple.pl
Executable file
|
@ -0,0 +1,28 @@
|
||||||
|
#!/usr/bin/perl
|
||||||
|
# Some simple tests for pidl
|
||||||
|
# (C) 2005 Jelmer Vernooij <jelmer@samba.org>
|
||||||
|
# Published under the GNU General Public License
|
||||||
|
use strict;
|
||||||
|
|
||||||
|
use Test::More tests => 8;
|
||||||
|
use FindBin qw($RealBin);
|
||||||
|
use lib "$RealBin";
|
||||||
|
use Util qw(test_samba4_ndr);
|
||||||
|
|
||||||
|
test_samba4_ndr("simple", "void Test(); ",
|
||||||
|
"
|
||||||
|
uint8_t data[] = { 0x02 };
|
||||||
|
uint8_t result;
|
||||||
|
DATA_BLOB b;
|
||||||
|
struct ndr_pull *ndr;
|
||||||
|
|
||||||
|
b.data = data;
|
||||||
|
b.length = 1;
|
||||||
|
ndr = ndr_pull_init_blob(&b, mem_ctx, NULL);
|
||||||
|
|
||||||
|
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_pull_uint8(ndr, NDR_SCALARS, &result)))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
if (result != 0x02)
|
||||||
|
return 2;
|
||||||
|
");
|
192
tools/pidl/tests/ndr_string.pl
Executable file
192
tools/pidl/tests/ndr_string.pl
Executable file
|
@ -0,0 +1,192 @@
|
||||||
|
#!/usr/bin/perl
|
||||||
|
# String tests for pidl
|
||||||
|
# (C) 2005 Jelmer Vernooij <jelmer@samba.org>
|
||||||
|
# Published under the GNU General Public License
|
||||||
|
use strict;
|
||||||
|
|
||||||
|
use Test::More tests => 6 * 8;
|
||||||
|
use FindBin qw($RealBin);
|
||||||
|
use lib "$RealBin";
|
||||||
|
use Util qw(test_samba4_ndr);
|
||||||
|
|
||||||
|
test_samba4_ndr("string-pull-empty",
|
||||||
|
' [public] void TestString([in,flag(STR_ASCII|LIBNDR_FLAG_STR_SIZE4)] string data);',
|
||||||
|
'
|
||||||
|
uint8_t data[] = { 0x00, 0x00, 0x00, 0x00 };
|
||||||
|
DATA_BLOB b = { data, 4 };
|
||||||
|
struct ndr_pull *ndr = ndr_pull_init_blob(&b, NULL);
|
||||||
|
struct TestString r;
|
||||||
|
r.in.data = NULL;
|
||||||
|
|
||||||
|
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_pull_TestString(ndr, NDR_IN, &r)))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
if (r.in.data == NULL)
|
||||||
|
return 2;
|
||||||
|
|
||||||
|
if (r.in.data[0] != 0)
|
||||||
|
return 3;
|
||||||
|
');
|
||||||
|
|
||||||
|
test_samba4_ndr("string-ascii-pull",
|
||||||
|
'
|
||||||
|
[public] void TestString([in,flag(STR_ASCII|LIBNDR_FLAG_STR_SIZE4)] string data);
|
||||||
|
',
|
||||||
|
'
|
||||||
|
uint8_t data[] = { 0x03, 0x00, 0x00, 0x00,
|
||||||
|
\'f\', \'o\', \'o\', 0 };
|
||||||
|
DATA_BLOB b = { data, 8 };
|
||||||
|
struct ndr_pull *ndr = ndr_pull_init_blob(&b, NULL);
|
||||||
|
struct TestString r;
|
||||||
|
r.in.data = NULL;
|
||||||
|
|
||||||
|
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_pull_TestString(ndr, NDR_IN, &r)))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
if (r.in.data == NULL)
|
||||||
|
return 2;
|
||||||
|
|
||||||
|
if (strncmp(r.in.data, "foo", 3) != 0)
|
||||||
|
return 3;
|
||||||
|
|
||||||
|
if (r.in.data[4] != 0)
|
||||||
|
return 4;
|
||||||
|
');
|
||||||
|
|
||||||
|
test_samba4_ndr("string-wchar-fixed-array-01",
|
||||||
|
'
|
||||||
|
typedef struct {
|
||||||
|
uint32 l1;
|
||||||
|
[string,charset(UTF16)] uint16 str[6];
|
||||||
|
uint32 l2;
|
||||||
|
} TestStringStruct;
|
||||||
|
|
||||||
|
[public] void TestString([in,ref] TestStringStruct *str);
|
||||||
|
',
|
||||||
|
'
|
||||||
|
uint8_t data[] = { 0x01, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x04, 0x00, 0x00, 0x00,
|
||||||
|
\'f\', 0x00, \'o\', 0x00,
|
||||||
|
\'o\', 0x00, 0x00, 0x00,
|
||||||
|
0x02, 0x00, 0x00, 0x00
|
||||||
|
};
|
||||||
|
DATA_BLOB b = { data, sizeof(data) };
|
||||||
|
struct ndr_pull *ndr = ndr_pull_init_blob(&b, NULL);
|
||||||
|
struct TestString r;
|
||||||
|
struct TestStringStruct str;
|
||||||
|
r.in.str = &str;
|
||||||
|
|
||||||
|
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_pull_TestString(ndr, NDR_IN, &r)))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
if (r.in.str == NULL)
|
||||||
|
return 2;
|
||||||
|
|
||||||
|
if (r.in.str->l1 != 0x00000001)
|
||||||
|
return 3;
|
||||||
|
|
||||||
|
if (strncmp(str.str, "foo", 3) != 0)
|
||||||
|
return 4;
|
||||||
|
|
||||||
|
if (r.in.str->str[4] != 0)
|
||||||
|
return 5;
|
||||||
|
|
||||||
|
if (r.in.str->l2 != 0x00000002)
|
||||||
|
return 6;
|
||||||
|
');
|
||||||
|
|
||||||
|
test_samba4_ndr("string-wchar-fixed-array-02",
|
||||||
|
'
|
||||||
|
typedef struct {
|
||||||
|
uint32 l1;
|
||||||
|
[string,charset(UTF16)] uint16 str[6];
|
||||||
|
uint32 l2;
|
||||||
|
} TestStringStruct;
|
||||||
|
|
||||||
|
[public] void TestString([in,ref] TestStringStruct *str);
|
||||||
|
',
|
||||||
|
'
|
||||||
|
uint8_t data[] = { 0x01, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x06, 0x00, 0x00, 0x00,
|
||||||
|
\'f\', 0x00, \'o\', 0x00,
|
||||||
|
\'o\', 0x00, \'b\', 0x00,
|
||||||
|
\'a\', 0x00, \'r\', 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x02, 0x00, 0x00, 0x00
|
||||||
|
};
|
||||||
|
DATA_BLOB b = { data, sizeof(data) };
|
||||||
|
struct ndr_pull *ndr = ndr_pull_init_blob(&b, NULL);
|
||||||
|
struct TestString r;
|
||||||
|
struct TestStringStruct str;
|
||||||
|
r.in.str = &str;
|
||||||
|
|
||||||
|
/* the string terminator is wrong */
|
||||||
|
if (NDR_ERR_CODE_IS_SUCCESS(ndr_pull_TestString(ndr, NDR_IN, &r)))
|
||||||
|
return 1;
|
||||||
|
');
|
||||||
|
|
||||||
|
test_samba4_ndr("string-wchar-fixed-array-03",
|
||||||
|
'
|
||||||
|
typedef struct {
|
||||||
|
uint32 l1;
|
||||||
|
[string,charset(UTF16)] uint16 str[6];
|
||||||
|
uint32 l2;
|
||||||
|
} TestStringStruct;
|
||||||
|
|
||||||
|
[public] void TestString([in,ref] TestStringStruct *str);
|
||||||
|
',
|
||||||
|
'
|
||||||
|
uint8_t data[] = { 0x01, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x07, 0x00, 0x00, 0x00,
|
||||||
|
\'f\', 0x00, \'o\', 0x00,
|
||||||
|
\'o\', 0x00, \'b\', 0x00,
|
||||||
|
\'a\', 0x00, \'r\', 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x02, 0x00, 0x00, 0x00
|
||||||
|
};
|
||||||
|
DATA_BLOB b = { data, sizeof(data) };
|
||||||
|
struct ndr_pull *ndr = ndr_pull_init_blob(&b, NULL);
|
||||||
|
struct TestString r;
|
||||||
|
struct TestStringStruct str;
|
||||||
|
r.in.str = &str;
|
||||||
|
|
||||||
|
/* the length 0x07 is to large */
|
||||||
|
if (NDR_ERR_CODE_IS_SUCCESS(ndr_pull_TestString(ndr, NDR_IN, &r)))
|
||||||
|
return 1;
|
||||||
|
');
|
||||||
|
|
||||||
|
SKIP: {
|
||||||
|
skip "doesn't seem to work yet", 8;
|
||||||
|
|
||||||
|
test_samba4_ndr("string-out",
|
||||||
|
'
|
||||||
|
[public] void TestString([out,string,charset(UNIX)] uint8 **data);
|
||||||
|
',
|
||||||
|
'
|
||||||
|
uint8_t data[] = { 0x03, 0x00, 0x00, 0x00,
|
||||||
|
\'f\', \'o\', \'o\', 0 };
|
||||||
|
DATA_BLOB b = { data, 8 };
|
||||||
|
struct ndr_pull *ndr = ndr_pull_init_blob(&b, NULL);
|
||||||
|
struct TestString r;
|
||||||
|
char *str = NULL;
|
||||||
|
r.out.data = &str;
|
||||||
|
|
||||||
|
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_pull_TestString(ndr, NDR_IN, &r)))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
if (r.out.data == NULL)
|
||||||
|
return 2;
|
||||||
|
|
||||||
|
if (*r.out.data == NULL)
|
||||||
|
return 3;
|
||||||
|
|
||||||
|
if (strncmp(r.out.data, "foo", 3) != 0)
|
||||||
|
return 4;
|
||||||
|
|
||||||
|
if (r.out.data[4] != 0)
|
||||||
|
return 5;
|
||||||
|
');
|
||||||
|
}
|
66
tools/pidl/tests/ndr_tagtype.pl
Executable file
66
tools/pidl/tests/ndr_tagtype.pl
Executable file
|
@ -0,0 +1,66 @@
|
||||||
|
#!/usr/bin/perl
|
||||||
|
# Support for tagged types
|
||||||
|
# (C) 2005 Jelmer Vernooij. Published under the GNU GPL
|
||||||
|
use strict;
|
||||||
|
|
||||||
|
use Test::More tests => 3 * 8;
|
||||||
|
use FindBin qw($RealBin);
|
||||||
|
use lib "$RealBin";
|
||||||
|
use Util qw(test_samba4_ndr);
|
||||||
|
|
||||||
|
test_samba4_ndr('struct-notypedef', '[public] struct bla { uint8 x; }; ',
|
||||||
|
'
|
||||||
|
struct ndr_push *ndr = ndr_push_init_ctx(NULL, NULL);
|
||||||
|
struct bla r;
|
||||||
|
uint8_t expected[] = { 0x0D };
|
||||||
|
DATA_BLOB expected_blob = { expected, 1 };
|
||||||
|
DATA_BLOB result_blob;
|
||||||
|
r.x = 13;
|
||||||
|
|
||||||
|
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_push_STRUCT_bla(ndr, NDR_SCALARS|NDR_BUFFERS, &r)))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
result_blob = ndr_push_blob(ndr);
|
||||||
|
|
||||||
|
if (data_blob_cmp(&result_blob, &expected_blob) != 0)
|
||||||
|
return 2;
|
||||||
|
');
|
||||||
|
|
||||||
|
test_samba4_ndr('struct-notypedef-used', '[public] struct bla { uint8 x; };
|
||||||
|
[public] void myfn([in] struct bla r); ',
|
||||||
|
'
|
||||||
|
struct ndr_push *ndr = ndr_push_init_ctx(NULL, NULL);
|
||||||
|
struct myfn fn;
|
||||||
|
uint8_t expected[] = { 0x0D };
|
||||||
|
DATA_BLOB expected_blob = { expected, 1 };
|
||||||
|
DATA_BLOB result_blob;
|
||||||
|
fn.in.r.x = 13;
|
||||||
|
|
||||||
|
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_push_myfn(ndr, NDR_IN, &fn)))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
result_blob = ndr_push_blob(ndr);
|
||||||
|
|
||||||
|
if (data_blob_cmp(&result_blob, &expected_blob) != 0)
|
||||||
|
return 2;
|
||||||
|
');
|
||||||
|
|
||||||
|
|
||||||
|
test_samba4_ndr('struct-notypedef-embedded', 'struct bla { uint8 x; };
|
||||||
|
[public] struct myst { struct bla r; }; ',
|
||||||
|
'
|
||||||
|
struct ndr_push *ndr = ndr_push_init_ctx(NULL, NULL);
|
||||||
|
struct myst st;
|
||||||
|
uint8_t expected[] = { 0x0D };
|
||||||
|
DATA_BLOB expected_blob = { expected, 1 };
|
||||||
|
DATA_BLOB result_blob;
|
||||||
|
st.r.x = 13;
|
||||||
|
|
||||||
|
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_push_STRUCT_myst(ndr, NDR_IN, &st)))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
result_blob = ndr_push_blob(ndr);
|
||||||
|
|
||||||
|
if (data_blob_cmp(&result_blob, &expected_blob) != 0)
|
||||||
|
return 2;
|
||||||
|
');
|
243
tools/pidl/tests/parse_idl.pl
Executable file
243
tools/pidl/tests/parse_idl.pl
Executable file
|
@ -0,0 +1,243 @@
|
||||||
|
#!/usr/bin/perl
|
||||||
|
# Some simple tests for pidls parsing routines
|
||||||
|
# (C) 2005 Jelmer Vernooij <jelmer@samba.org>
|
||||||
|
# Published under the GNU General Public License
|
||||||
|
use strict;
|
||||||
|
|
||||||
|
use Test::More tests => 65 * 2 + 7;
|
||||||
|
use FindBin qw($RealBin);
|
||||||
|
use lib "$RealBin";
|
||||||
|
use Util qw(test_errors);
|
||||||
|
use Parse::Pidl::IDL;
|
||||||
|
use Parse::Pidl::NDR;
|
||||||
|
|
||||||
|
sub testok($$)
|
||||||
|
{
|
||||||
|
my ($name, $data) = @_;
|
||||||
|
|
||||||
|
test_errors("", sub {
|
||||||
|
my $pidl = Parse::Pidl::IDL::parse_string($data, "<$name>");
|
||||||
|
ok (defined($pidl), $name);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
sub testfail($$$)
|
||||||
|
{
|
||||||
|
my ($name, $data, $error) = @_;
|
||||||
|
|
||||||
|
test_errors($error, sub {
|
||||||
|
my $pidl = Parse::Pidl::IDL::parse_string($data, "<$name>");
|
||||||
|
|
||||||
|
ok ((not defined $pidl), $name);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
testfail "unknowntag", "bla test {};",
|
||||||
|
"<unknowntag>:0: Syntax error near 'bla'\n";
|
||||||
|
testok "test1", "interface test { void Test(); }; ";
|
||||||
|
testok "voidtest", "interface test { int Testx(void); }; ";
|
||||||
|
testfail "voidtest", "interface test { Test(); }; ",
|
||||||
|
"<voidtest>:0: Syntax error near '('\n";
|
||||||
|
testok "argtest", "interface test { int Test(int a, long b, uint32 c); }; ";
|
||||||
|
testok "array1", "interface test { int Test(int a[]); };";
|
||||||
|
testok "array2", "interface test { int Test(int a[2]); };";
|
||||||
|
testok "array3", "interface test { int Test(int a[b]); };";
|
||||||
|
testfail "array4", "interface test { int Test(int[] a); };",
|
||||||
|
"<array4>:0: Syntax error near '['\n";
|
||||||
|
testok "ptr1", "interface test { int Test(int *a); };";
|
||||||
|
testok "ptr2", "interface test { int Test(int **a); };";
|
||||||
|
testok "ptr3", "interface test { int Test(int ***a); };";
|
||||||
|
testfail "empty1", "interface test { };", "<empty1>:0: Syntax error near '}'\n";
|
||||||
|
testfail "empty2", "", "";
|
||||||
|
testok "attr1", "[uuid(\"myuuid\"),attr] interface test { int Test(int ***a); };";
|
||||||
|
testok "attr2", "interface test { [public] int Test(); };";
|
||||||
|
testok "attr3", "[attr1] [attr2] interface test { [public] int Test(); };";
|
||||||
|
testok "multfn", "interface test { int test1(); int test2(); };";
|
||||||
|
testok "multif", "interface test { int test1(); }; interface test2 { int test2(); };";
|
||||||
|
testok "tdstruct1", "interface test { typedef struct { } foo; };";
|
||||||
|
testok "tdstruct2", "interface test { typedef struct { int a; } foo; };";
|
||||||
|
testok "tdstruct3", "interface test { typedef struct { int a; int b; } foo; };";
|
||||||
|
testfail "tdstruct4", "interface test { typedef struct { int a, int b; } foo; };",
|
||||||
|
"<tdstruct4>:0: Syntax error near ','\n";
|
||||||
|
testok "struct1", "interface test { struct x { }; };";
|
||||||
|
testok "struct2", "interface test { struct x { int a; }; };";
|
||||||
|
testok "struct3", "interface test { struct x { int a; int b; }; };";
|
||||||
|
testfail "struct4", "interface test { struct x { int a, int b; }; };",
|
||||||
|
"<struct4>:0: Syntax error near ','\n";
|
||||||
|
testfail "struct5", "interface test { struct { int a; } x; };",
|
||||||
|
"<struct5>:0: Syntax error near 'x'\n";
|
||||||
|
testok "tdunion1", "interface test { typedef union { } a; };";
|
||||||
|
testok "tdunion2", "interface test { typedef union { int a; } a; };";
|
||||||
|
testok "union1", "interface test { union a { }; };";
|
||||||
|
testok "union2", "interface test { union x { int a; }; };";
|
||||||
|
testfail "union3", "interface test { union { int a; } x; };",
|
||||||
|
"<union3>:0: Syntax error near 'x'\n";
|
||||||
|
testok "typedef1", "interface test { typedef int a; };";
|
||||||
|
testfail "typedef2", "interface test { typedef x; };",
|
||||||
|
"<typedef2>:0: Syntax error near ';'\n";
|
||||||
|
testok "tdenum1", "interface test { typedef enum { A=1, B=2, C} a; };";
|
||||||
|
testok "enum1", "interface test { enum a { A=1, B=2, C}; };";
|
||||||
|
testfail "enum2", "interface test { enum { A=1, B=2, C} a; };",
|
||||||
|
"<enum2>:0: Syntax error near 'a'\n";
|
||||||
|
testok "nested1", "interface test { struct x { struct { int a; } z; }; };";
|
||||||
|
testok "nested2", "interface test { struct x { struct y { int a; } z; }; };";
|
||||||
|
testok "bitmap1", "interface test { bitmap x { a=1 }; };";
|
||||||
|
testok "unsigned", "interface test { struct x { unsigned short y; }; };";
|
||||||
|
testok "struct-property", "interface test { [public] struct x { short y; }; };";
|
||||||
|
testok "signed", "interface test { struct x { signed short y; }; };";
|
||||||
|
testok "declarg", "interface test { void test(struct { int x; } a); };";
|
||||||
|
testok "structarg", "interface test { void test(struct a b); };";
|
||||||
|
testfail "structargmissing", "interface test { void test(struct a); };",
|
||||||
|
"<structargmissing>:0: Syntax error near ')'\n";
|
||||||
|
testok "structqual", "interface test { struct x { struct y z; }; };";
|
||||||
|
testok "unionqual", "interface test { struct x { union y z; }; };";
|
||||||
|
testok "enumqual", "interface test { struct x { enum y z; }; };";
|
||||||
|
testok "bitmapqual", "interface test { struct x { bitmap y z; }; };";
|
||||||
|
testok "emptystructdecl", "interface test { struct x; };";
|
||||||
|
testok "emptyenumdecl", "interface test { enum x; };";
|
||||||
|
testok "emptytdstructdecl", "interface test { typedef struct x y; };";
|
||||||
|
testok "import", "import \"foo.idl\";";
|
||||||
|
testok "include", "include \"foo.h\";";
|
||||||
|
testfail "import-noquotes", "import foo.idl;",
|
||||||
|
"<import-noquotes>:0: Syntax error near 'foo'\n";
|
||||||
|
testfail "include-noquotes", "include foo.idl;",
|
||||||
|
"<include-noquotes>:0: Syntax error near 'foo'\n";
|
||||||
|
testok "importlib", "importlib \"foo.idl\";";
|
||||||
|
testfail "import-nosemicolon", "import \"foo.idl\"",
|
||||||
|
"<import-nosemicolon>:0: Syntax error near 'foo.idl'\n";
|
||||||
|
testok "import-multiple", "import \"foo.idl\", \"bar.idl\";";
|
||||||
|
testok "include-multiple", "include \"foo.idl\", \"bar.idl\";";
|
||||||
|
testok "empty-struct", "interface test { struct foo { }; }";
|
||||||
|
testok "typedef-double", "interface test { typedef struct foo { } foo; }";
|
||||||
|
testok "cpp-quote", "cpp_quote(\"bla\")";
|
||||||
|
|
||||||
|
my $x = Parse::Pidl::IDL::parse_string("interface foo { struct x {}; }", "<foo>");
|
||||||
|
|
||||||
|
is_deeply($x, [ {
|
||||||
|
'TYPE' => 'INTERFACE',
|
||||||
|
'NAME' => 'foo',
|
||||||
|
'DATA' => [ {
|
||||||
|
'TYPE' => 'STRUCT',
|
||||||
|
'NAME' => 'x',
|
||||||
|
'ELEMENTS' => [],
|
||||||
|
'FILE' => '<foo>',
|
||||||
|
'LINE' => 0
|
||||||
|
} ],
|
||||||
|
'FILE' => '<foo>',
|
||||||
|
'LINE' => 0
|
||||||
|
}]);
|
||||||
|
|
||||||
|
$x = Parse::Pidl::IDL::parse_string("interface foo { struct x; }", "<foo>");
|
||||||
|
is_deeply($x, [ {
|
||||||
|
'TYPE' => 'INTERFACE',
|
||||||
|
'NAME' => 'foo',
|
||||||
|
'DATA' => [ {
|
||||||
|
'TYPE' => 'STRUCT',
|
||||||
|
'NAME' => 'x',
|
||||||
|
'FILE' => '<foo>',
|
||||||
|
'LINE' => 0
|
||||||
|
} ],
|
||||||
|
'FILE' => '<foo>',
|
||||||
|
'LINE' => 0
|
||||||
|
}]);
|
||||||
|
|
||||||
|
$x = Parse::Pidl::IDL::parse_string("cpp_quote(\"foobar\")", "<quote>");
|
||||||
|
is_deeply($x, [ {
|
||||||
|
'TYPE' => 'CPP_QUOTE',
|
||||||
|
'DATA' => '"foobar"',
|
||||||
|
'FILE' => '<quote>',
|
||||||
|
'LINE' => 0
|
||||||
|
}]);
|
||||||
|
|
||||||
|
# A typedef of a struct without body
|
||||||
|
$x = Parse::Pidl::IDL::parse_string("interface foo { typedef struct x y; }", "<foo>");
|
||||||
|
|
||||||
|
is_deeply($x, [ {
|
||||||
|
'TYPE' => 'INTERFACE',
|
||||||
|
'NAME' => 'foo',
|
||||||
|
'DATA' => [ {
|
||||||
|
'TYPE' => 'TYPEDEF',
|
||||||
|
'NAME' => 'y',
|
||||||
|
'POINTERS' => 0,
|
||||||
|
'DATA' => {
|
||||||
|
'TYPE' => 'STRUCT',
|
||||||
|
'NAME' => 'x',
|
||||||
|
'FILE' => '<foo>',
|
||||||
|
'LINE' => 0,
|
||||||
|
},
|
||||||
|
'FILE' => '<foo>',
|
||||||
|
'LINE' => 0,
|
||||||
|
} ],
|
||||||
|
'FILE' => '<foo>',
|
||||||
|
'LINE' => 0
|
||||||
|
}]);
|
||||||
|
|
||||||
|
# A typedef of a struct with empty body
|
||||||
|
$x = Parse::Pidl::IDL::parse_string("interface foo { typedef struct {} y; }", "<foo>");
|
||||||
|
|
||||||
|
is_deeply($x, [ {
|
||||||
|
'TYPE' => 'INTERFACE',
|
||||||
|
'NAME' => 'foo',
|
||||||
|
'DATA' => [ {
|
||||||
|
'TYPE' => 'TYPEDEF',
|
||||||
|
'NAME' => 'y',
|
||||||
|
'POINTERS' => 0,
|
||||||
|
'DATA' => {
|
||||||
|
'TYPE' => 'STRUCT',
|
||||||
|
'ELEMENTS' => [],
|
||||||
|
'FILE' => '<foo>',
|
||||||
|
'LINE' => 0
|
||||||
|
},
|
||||||
|
'FILE' => '<foo>',
|
||||||
|
'LINE' => 0
|
||||||
|
} ],
|
||||||
|
'FILE' => '<foo>',
|
||||||
|
'LINE' => 0
|
||||||
|
}]);
|
||||||
|
|
||||||
|
# A typedef of a bitmap with no body
|
||||||
|
$x = Parse::Pidl::IDL::parse_string("interface foo { typedef bitmap x y; }", "<foo>");
|
||||||
|
|
||||||
|
is_deeply($x, [ {
|
||||||
|
'TYPE' => 'INTERFACE',
|
||||||
|
'NAME' => 'foo',
|
||||||
|
'DATA' => [ {
|
||||||
|
'TYPE' => 'TYPEDEF',
|
||||||
|
'NAME' => 'y',
|
||||||
|
'POINTERS' => 0,
|
||||||
|
'DATA' => {
|
||||||
|
'TYPE' => 'BITMAP',
|
||||||
|
'NAME' => 'x',
|
||||||
|
'FILE' => '<foo>',
|
||||||
|
'LINE' => 0
|
||||||
|
},
|
||||||
|
'FILE' => '<foo>',
|
||||||
|
'LINE' => 0
|
||||||
|
} ],
|
||||||
|
'FILE' => '<foo>',
|
||||||
|
'LINE' => 0
|
||||||
|
}]);
|
||||||
|
|
||||||
|
|
||||||
|
# A typedef of a union with no body
|
||||||
|
$x = Parse::Pidl::IDL::parse_string("interface foo { typedef union x y; }", "<foo>");
|
||||||
|
|
||||||
|
is_deeply($x, [ {
|
||||||
|
'TYPE' => 'INTERFACE',
|
||||||
|
'NAME' => 'foo',
|
||||||
|
'DATA' => [ {
|
||||||
|
'TYPE' => 'TYPEDEF',
|
||||||
|
'NAME' => 'y',
|
||||||
|
'POINTERS' => 0,
|
||||||
|
'DATA' => {
|
||||||
|
'TYPE' => 'UNION',
|
||||||
|
'NAME' => 'x',
|
||||||
|
'FILE' => '<foo>',
|
||||||
|
'LINE' => 0
|
||||||
|
},
|
||||||
|
'FILE' => '<foo>',
|
||||||
|
'LINE' => 0
|
||||||
|
} ],
|
||||||
|
'FILE' => '<foo>',
|
||||||
|
'LINE' => 0
|
||||||
|
}]);
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user