source: svn/trunk/newcon3bcm2_21bu/nexus/build/tools/kernelproxy/bapi_driver_ioctl.pm

Last change on this file was 2, checked in by phkim, 11 years ago

1.phkim

  1. revision copy newcon3sk r27
  • Property svn:executable set to *
File size: 26.7 KB
Line 
1#!/usr/bin/perl
2#     (c)2003-2011 Broadcom Corporation
3#
4#  This program is the proprietary software of Broadcom Corporation and/or its licensors,
5#  and may only be used, duplicated, modified or distributed pursuant to the terms and
6#  conditions of a separate, written license agreement executed between you and Broadcom
7#  (an "Authorized License").  Except as set forth in an Authorized License, Broadcom grants
8#  no license (express or implied), right to use, or waiver of any kind with respect to the
9#  Software, and Broadcom expressly reserves all rights in and to the Software and all
10#  intellectual property rights therein.  IF YOU HAVE NO AUTHORIZED LICENSE, THEN YOU
11#  HAVE NO RIGHT TO USE THIS SOFTWARE IN ANY WAY, AND SHOULD IMMEDIATELY
12#  NOTIFY BROADCOM AND DISCONTINUE ALL USE OF THE SOFTWARE.
13#
14#  Except as expressly set forth in the Authorized License,
15#
16#  1.     This program, including its structure, sequence and organization, constitutes the valuable trade
17#  secrets of Broadcom, and you shall use all reasonable efforts to protect the confidentiality thereof,
18#  and to use this information only in connection with your use of Broadcom integrated circuit products.
19#
20#  2.     TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
21#  AND WITH ALL FAULTS AND BROADCOM MAKES NO PROMISES, REPRESENTATIONS OR
22#  WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT TO
23#  THE SOFTWARE.  BROADCOM SPECIFICALLY DISCLAIMS ANY AND ALL IMPLIED WARRANTIES
24#  OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR PURPOSE,
25#  LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET POSSESSION
26#  OR CORRESPONDENCE TO DESCRIPTION. YOU ASSUME THE ENTIRE RISK ARISING OUT OF
27#  USE OR PERFORMANCE OF THE SOFTWARE.
28#
29#  3.     TO THE MAXIMUM EXTENT PERMITTED BY LAW, IN NO EVENT SHALL BROADCOM OR ITS
30#  LICENSORS BE LIABLE FOR (i) CONSEQUENTIAL, INCIDENTAL, SPECIAL, INDIRECT, OR
31#  EXEMPLARY DAMAGES WHATSOEVER ARISING OUT OF OR IN ANY WAY RELATING TO YOUR
32#  USE OF OR INABILITY TO USE THE SOFTWARE EVEN IF BROADCOM HAS BEEN ADVISED OF
33#  THE POSSIBILITY OF SUCH DAMAGES; OR (ii) ANY AMOUNT IN EXCESS OF THE AMOUNT
34#  ACTUALLY PAID FOR THE SOFTWARE ITSELF OR U.S. $1, WHICHEVER IS GREATER. THESE
35#  LIMITATIONS SHALL APPLY NOTWITHSTANDING ANY FAILURE OF ESSENTIAL PURPOSE OF
36#  ANY LIMITED REMEDY.
37#
38# $brcm_Workfile: bapi_driver_ioctl.pm $
39# $brcm_Revision: 53 $
40# $brcm_Date: 12/7/11 10:41a $
41#
42# File Description:
43#
44# Revision History:
45#
46# $brcm_Log: /nexus/build/tools/kernelproxy/bapi_driver_ioctl.pm $
47#
48# 53   12/7/11 10:41a erickson
49# SW7420-2141: merge as much duplicated kernelmode proxy/usermode ipc
50#  perl code as possible
51#
52# 52   11/7/11 3:59p bandrews
53# SW7231-446: merge to main
54#
55# SW7231-446/2   11/4/11 9:44p bandrews
56# SW7231-446: fix based on review
57#
58# SW7231-446/1   11/3/11 9:27p bandrews
59# SW7231-446: implemented
60#
61# 51   11/1/11 9:57a erickson
62# SW7231-391: add typecast
63#
64# 50   11/1/11 9:29a erickson
65# SW7231-391: add typecast for nexus_driver_verify_<handletype> calls
66#
67# 49   10/17/11 1:09p erickson
68# SW7418-40: fix size of copy_from_user for main ioctl struct
69#
70# 48   9/20/11 11:02a erickson
71# SW7420-1148: check attr{null_allowed} for NEXUS_HeapHandle function
72#  param
73#
74# 47   9/13/11 1:23p erickson
75# SW7420-1148: change client modes to unprotected/protected/untrusted
76#
77# 46   9/13/11 10:56a erickson
78# SW7420-1689: NEXUS_HeapHandle is validated, even though it is not a
79#  class
80#
81# 45   9/2/11 12:39p erickson
82# SW7420-1148: refactor class_list.pl to generate per-module "get current
83#  client" functions
84#
85# 44   9/2/11 10:03a erickson
86# SW7420-1148: allow nexus_register/unregister to objdb from nexus
87#  module. enables more complex resource management.
88#
89# 43   8/31/11 12:18p erickson
90# SW7231-357: don't generate server-side code for attr{local=true}
91#  functions
92#
93# 42   8/23/11 4:13p erickson
94# SW7420-1992: rename to surface_compositor
95#
96# 41   8/22/11 2:14p erickson
97# SW7420-1689: back out last change. will require more work.
98#
99# 40   8/11/11 11:31a erickson
100# SW7420-1689: must do class_verification before driver_pre_call to avoid
101#  leaks if not verified
102#
103# 39   8/8/11 5:10p erickson
104# SW7420-1689: add untrusted client api enforcement
105#
106# 38   8/3/11 9:57a erickson
107# SW7420-1992: add per-display framebuffer heap to
108#  NEXUS_SurfaceCmpSettings
109#
110# 37   8/2/11 4:25p erickson
111# SW7420-1979: autogen nexus_driver_shutdown_close, used by class table
112#  and ioctl, to process SHUTDOWN attribute prior to close
113#
114# 36   7/29/11 12:13p erickson
115# SW7420-1991: reorganize to allow ipcthunk/bapi_common.pm layout to be
116#  closer
117#
118# 35   7/12/11 1:26p erickson
119# SW7420-1979: add support for new shutdown attribute
120#
121# 34   5/16/11 4:14p erickson
122# SW7420-1679: NEXUS_Memory_Free must check pointer with objdb before
123#  freeing
124#
125# 33   5/13/11 12:17p erickson
126# SW7420-1873: remove shutdown attribute
127#
128# 32   5/3/11 5:08p erickson
129# SW7420-1819: repartition so NFE is a standard feature
130#
131# 31   4/14/11 11:59a erickson
132# SW7420-1679: clean up NEXUS_Memory_Allocate using
133#  attr{dealloc=NEXUS_Memory_Free}
134#
135# 30   4/7/11 5:23p erickson
136# SW7420-1671: use BERR_TRACE in proxy
137#
138# 29   4/1/11 9:59a erickson
139# SW7420-1671: refactor object database for multiprocess stress
140#
141# 28   3/3/11 11:57a erickson
142# SWDTV-5533: support up to 512 ioctl's per nexus module
143#
144# 27   2/15/11 2:16p erickson
145# SW7420-1148: support NEXUS_HeapHandle as func param, add error line
146#  numbers
147#
148# 26   1/28/11 9:03a erickson
149# SW7420-1440: refactor secondary_destructor
150#
151# 25   1/19/11 3:42p erickson
152# SW7420-1123: refactor kernelproxy to correspond to usermode changes
153#
154# 24   1/19/11 2:02p erickson
155# SW7420-1123: socket-based usermode IPC
156#
157# 23   12/14/10 4:37p erickson
158# SW7420-1285: null_allowed attribute is now required
159#
160# 22   12/7/10 5:47p erickson
161# SW7420-1148: refactor kernel mode proxy for process isolation
162#
163# 21   10/14/10 5:05p erickson
164# SW7420-1148: remove leftover debug
165#
166# 20   10/14/10 12:34p erickson
167# SW7420-1148: add secondary_destructor to support
168#  NEXUS_Playpump_ClosePidChannel, verify function attr in one place,
169#  support multiple param verifications per ioctl
170#
171# 19   10/12/10 4:29p erickson
172# SW7420-1148: refactor kernel mode proxy for process isolation
173#
174# 18   10/7/10 11:22a erickson
175# SW7420-1148: add client_id
176#
177# 17   6/15/10 4:46p erickson
178# SW7405-4011: remove NEXUS_StopCallbacks in driver that can deadlock
179#
180# 16   6/10/10 4:56p vsilyaev
181# SW7405-4011: Added StopCallbacks into the driver ioctl code
182#
183# 15   5/13/10 3:59p jtna
184# SW7125-306: Coverity Defect ID:20562 USE_AFTER_FREE
185#
186# 14   2/5/10 4:02p jgarrett
187# SW7125-205: Fixing loop generating CREATE vs. USE code.  It was
188#  generating CREATE entries for everything and causing memory leaks on
189#  GetConnector.
190#
191# 13   7/24/08 6:09p vsilyaev
192# PR 45137: Modified INIT ioctl to pass application type
193#
194# 12   2/7/08 1:01p vsilyaev
195# PR 38682: Fixed check for destructor type
196#
197# 11   2/4/08 2:39p vsilyaev
198# PR 38682: Added support for pointers with variable size
199#
200# 10   2/1/08 5:02p vsilyaev
201# PR 38682: Added tracking of open/close calls
202#
203# 9   1/31/08 5:02p vsilyaev
204# PR 38682: Added function level attributes
205#
206# 8   1/30/08 6:18p vsilyaev
207# PR 38682: Added support for callbacks that are passed directly as
208#  function arguments
209#
210# 7   1/30/08 11:49a vsilyaev
211# PR 38682: Added routing of callbacks into the user space
212#
213# 6   1/28/08 12:51p vsilyaev
214# PR 38682: Fixed redundant mapping of addreses inside structures
215#
216# 5   1/28/08 12:33p vsilyaev
217# PR 38682: Added support for attribute tags applied to structure
218#  members.
219#
220# 4   1/25/08 4:24p vsilyaev
221# PR 38682: Reduce code size of the generated code
222#
223# 3   1/25/08 2:35p vsilyaev
224# PR 38682: Added handling of 'attr' to the function arguments
225#
226# 2   1/24/08 4:30p vsilyaev
227# PR 38682: Improved kernel/proxy environment
228#
229# 1   1/18/08 2:14p jgarrett
230# PR 38808: Merging to main branch
231#
232# Nexus_Devel/3   1/18/08 1:13p vsilyaev
233# PR 38682: Updated nexus kernel environment
234#
235#############################################################################
236use strict;
237
238package bapi_driver_ioctl;
239
240sub generate_class_code
241{
242    my ($classes, $func, $args) = @_;
243    my $id=0;
244    CLASS: for (@$classes) {
245        my $class = $_;
246        for (@{$class->{CONSTRUCTORS}}) {
247            if($_ == $func) {
248                if($class->{DESTRUCTOR_TYPE} eq 'destructor') {
249                    return ["NEXUS_DRIVER_CREATE_OBJECT($id, $args.ioctl.__retval);"];
250                }
251                elsif($class->{DESTRUCTOR_TYPE} eq 'dealloc') {
252                    # find param based on param dealloc attr
253                    my $param;
254                    for $param (@{$func->{PARAMS}}) {
255                        if (defined $param->{ATTR}->{'dealloc'}) {
256                            return ["NEXUS_DRIVER_CREATE_OBJECT($id, NEXUS_OffsetToCachedAddr((unsigned)$args.$param->{NAME}));"];
257                        }
258                    }
259                }
260                last CLASS;
261            }
262        }
263        if($class->{DESTRUCTOR} == $func) {
264            my $param =  @{$func->{PARAMS}}[0];
265            if($class->{DESTRUCTOR_TYPE} eq 'dealloc') {
266                return ["/* coverity[pass_freed_arg] */ ", "NEXUS_DRIVER_DESTROY_OBJECT($id, $args.ioctl.$param->{NAME});"];
267            }
268            else {
269                return ["/* coverity[pass_freed_arg] */ ", "NEXUS_DRIVER_DESTROY_OBJECT($id, $args.ioctl.$param->{NAME});"];
270            }
271        }
272        for (@{$class->{SECONDARY_DESTRUCTORS}}) {
273            if($_ == $func) {
274                my $param =  @{$func->{PARAMS}}[1];
275                return ["/* coverity[pass_freed_arg] */ ", "NEXUS_DRIVER_DESTROY_OBJECT($id, $args.ioctl.$param->{NAME});"];
276            }
277        }
278        if($class->{ACQUIRE} == $func) {
279            my $param =  @{$func->{PARAMS}}[0];
280            return ["NEXUS_DRIVER_ACQUIRE_OBJECT($id, $args.ioctl.__retval);"];
281        }
282        if($class->{RELEASE} == $func) {
283            my $param =  @{$func->{PARAMS}}[0];
284            return ["NEXUS_DRIVER_RELEASE_OBJECT($id, $args.ioctl.$param->{NAME});"];
285        }
286        $id++;
287    }
288    return undef;
289}
290
291# check if any function parameter or struct member is a class handle.
292# if so, generate code to verify the handle matches the instance and client.
293# also, check NEXUS_HeapHandle as a special case
294sub generate_class_verification
295{
296    my ($classes, $structs, $func, $args, $class_handles, $untrusted_api) = @_;
297    my @verify_lines;
298
299    # TODO: requires >2 levels of nested struct parsing in bapi_parse_c.pm. not required for now.
300    if ($func->{FUNCNAME} eq "NEXUS_SurfaceCompositor_SetSettings" ||
301        $func->{FUNCNAME} eq "NEXUS_SimpleAudioDecoder_Start")
302    {
303        return \@verify_lines;
304    }
305
306    # if untrusted, verify that this function can be called
307    if (!bapi_classes::callable_by_untrusted($func, $classes, $untrusted_api)) {
308        push @verify_lines, "if ((CLIENT_ID)->limited_api) {BERR_TRACE(-1); goto err_fault;}";
309    }
310
311    for (@{$func->{PARAMS}}) {
312        my $param = $_;
313        my $handletype;
314                my $param_field = "$args.ioctl.$param->{NAME}";
315
316        # check each class that was defined in this module
317        for (@$classes) {
318            my $class = $_;
319            $handletype = $class->{CLASS_TYPE};
320
321            # check if param is class handle
322            if ($param->{TYPE} eq $handletype) {
323                push @verify_lines, "if (nexus_driver_verify_$handletype(CLIENT_ID, (void*)${param_field})) {BERR_TRACE(-1); goto err_fault;}";
324            }
325            elsif ($param == @{$func->{PARAMS}}[0] &&
326                   $class->{DESTRUCTOR_TYPE} eq 'dealloc' && 
327                   $class->{DESTRUCTOR} == $func) {
328                push @verify_lines, "if (nexus_driver_verify_$handletype(CLIENT_ID, (void*)${param_field})) {BERR_TRACE(-1); goto err_fault;}";
329            }
330        }
331
332        foreach $handletype (@$class_handles) {
333            #print "generate_class_verification $handletype\n";
334            # check is param is a struct which has a class handle field
335            if ($param->{ISREF} && $param->{INPARAM} && exists $structs->{$param->{BASETYPE}}) {
336                my $struct_field;
337                for $struct_field (@{$structs->{$param->{BASETYPE}}}) {
338                    if ($struct_field->{TYPE} eq $handletype) {
339                        my $struct_param = "$args.$param->{NAME}.$struct_field->{NAME}";
340                        # verify non-NULL params
341                        push @verify_lines, "if(${param_field} && $struct_param) {";
342                        push @verify_lines, "  if (nexus_driver_verify_$handletype(CLIENT_ID, (void*)$struct_param)) {BERR_TRACE(-1); goto err_fault;}";
343                        push @verify_lines, "}";
344                    }
345                }
346            }
347        }
348
349        # check for timebase or parser band as struct member
350        # this code only checks input params
351        # output params post call are checked in bapi_common.pm
352        # TODO: doesn't support members as pointers
353        if ($param->{ISREF} && $param->{INPARAM} && exists $structs->{$param->{BASETYPE}}) {
354            my $struct_field;
355            for $struct_field (@{$structs->{$param->{BASETYPE}}}) {
356                if ($struct_field->{TYPE} eq 'NEXUS_Timebase' || $struct_field->{TYPE} eq 'NEXUS_ParserBand') {
357                    my $struct_param = "$args.$param->{NAME}.$struct_field->{NAME}";
358                    push @verify_lines, "if(nexus_driver_client_id(context)->config.mode != NEXUS_ClientMode_eUnprotected) {";
359                    push @verify_lines, "  if(${param_field}) {"; #ioctl pointer check replaces _isnull check
360                    push @verify_lines, "    if ((void *)$struct_param == NULL) {";
361                    push @verify_lines, "      $struct_param = $struct_field->{TYPE}_eInvalid;";
362                    push @verify_lines, "    }";
363                    push @verify_lines, "  }";
364                    push @verify_lines, "}";
365                }
366            }
367        }
368
369        # check for timebase or parser band as function param
370        # this code only checks input params
371        # output params post call are checked in bapi_common.pm
372        if ($param->{ISREF})
373        {
374            if ($param->{BASETYPE} eq 'NEXUS_Timebase' || $param->{BASETYPE} eq 'NEXUS_ParserBand')
375            {
376                if ($param->{INPARAM}) 
377                {
378                    push @verify_lines, "if (nexus_driver_client_id(context)->config.mode != NEXUS_ClientMode_eUnprotected) {";
379                    push @verify_lines, "  if (${param_field} != NULL) {"; # check pointer
380                    push @verify_lines, "    if ((void *)*${param_field} == NULL) {"; # check pointed to value
381                    push @verify_lines, "      *${param_field} = $param->{TYPE}_eInvalid;";
382                    push @verify_lines, "    }";
383                    push @verify_lines, "  }";
384                    push @verify_lines, "}";
385                }
386            }
387        }
388        else # pass by value is input implicitly
389        {
390            if ($param->{TYPE} eq 'NEXUS_Timebase' || $param->{TYPE} eq 'NEXUS_ParserBand') {
391                push @verify_lines, "if(nexus_driver_client_id(context)->config.mode != NEXUS_ClientMode_eUnprotected) {";
392                push @verify_lines, "  if((void *)${param_field} == NULL) {";
393                push @verify_lines, "    ${param_field} = $param->{TYPE}_eInvalid;";
394                push @verify_lines, "  }";
395                push @verify_lines, "}";
396            }
397        }
398
399        # check for heap handle as struct member
400        if ($param->{ISREF} && $param->{INPARAM} && exists $structs->{$param->{BASETYPE}}) {
401            my $struct_field;
402            for $struct_field (@{$structs->{$param->{BASETYPE}}}) {
403                if ($struct_field->{TYPE} eq 'NEXUS_HeapHandle') {
404                    my $struct_param = "$args.$param->{NAME}.$struct_field->{NAME}";
405                    # verify all heap handles, even if NULL
406                    push @verify_lines, "if(${param_field} ) {";
407                    push @verify_lines, "  if (NEXUS_DRIVER_VERIFY_HEAP($struct_param)) {BERR_TRACE(-1); goto err_fault;}";
408                    push @verify_lines, "}";
409                }
410            }
411        }
412
413        # check for heap handle as function param
414        if ($param->{TYPE} eq 'NEXUS_HeapHandle') {
415            # verify all heap handles, but honor null_allowed
416            my $null_allowed = $param->{ATTR}->{'null_allowed'};
417            if (!defined $null_allowed || $null_allowed eq "unprotected" || $null_allowed eq "trusted") {
418                if ($null_allowed eq "unprotected" || $null_allowed eq "trusted") {
419                    # allowed for unprotected code
420                    push @verify_lines, "if (!${param_field} && (CLIENT_ID)->verify != b_objdb_verify_none) {";
421                }
422                else {
423                    # never allowed
424                    push @verify_lines, "if (!${param_field}) {";
425                }
426                push @verify_lines, "  BDBG_ERR((\"NULL not allowed for $param->{NAME} param in $func->{FUNCNAME}: %d\", __LINE__));";
427                push @verify_lines, "  goto err_fault;";
428                push @verify_lines, "}";
429            }
430            push @verify_lines, "if (NEXUS_DRIVER_VERIFY_HEAP(${param_field})) {BERR_TRACE(-1); goto err_fault;}";
431        }
432    }
433   
434    # for destructors with shutdown attributes, we must call the auto-generated shutdown_close function
435    # instead of directly calling the normal close function.
436    my $class;
437    my $bypass;
438    for $class (@$classes) {
439        if ($class->{DESTRUCTOR} == $func && exists $class->{SHUTDOWN}) {
440            my $classtype = $class->{CLASS_TYPE};
441            my $params = $func->{PARAMS};
442            my $handle = "$args.ioctl.$$params[0]->{NAME}";
443            push @verify_lines, "nexus_driver_shutdown_close_$classtype($handle);";
444            $bypass = 1;
445        }
446    }
447   
448    return (\@verify_lines, $bypass);
449}
450
451sub generate_union
452{
453    my ($file, $module, $funcs, $structs) = @_;
454    my $func;
455    my $module_lc = lc $module;
456
457
458    print $file "/* union to store temporary copy of all in and out parameters */\n";
459    print $file "union nexus_driver_module_args {\n";
460    print $file "  PROXY_NEXUS_ModuleInit init;\n";
461    for $func (@$funcs) {
462        my $params = $func->{PARAMS};
463        my $param;
464        my @struct;
465        my $attr = bapi_common::process_function_attributes $func, $structs, $funcs;
466        if (!$func->{NOSTRUCT}) {
467            my $struct = bapi_common::ioctl_struct $module, $func;
468            print $file "  struct {\n";
469            print $file "     $struct ioctl;\n";
470            for $param (@$params) {
471                if ($param->{ISREF} && $param->{BASETYPE} ne 'void' && not (exists $attr->{'driver_overwrite'}->{$param->{NAME}}) ) {
472                    print $file "     $param->{BASETYPE} $param->{NAME};\n";
473                }
474            }
475            bapi_util::print_code $file, $attr->{'driver_ioctl_data'}, "     ";
476            print $file "  } $func->{FUNCNAME};  \n";
477        }
478    }
479    print $file "};\n";
480}
481
482sub case_ioctl
483{
484    my $module = shift;
485    my $ioctl = shift;
486    return <<ENDCASE;
487 case NEXUS_IOCTL_NUM($ioctl):
488ENDCASE
489}
490
491sub generate_ioctl
492{
493    my ($file, $module, $version, $structs, $classes, $funcs, $class_handles, $untrusted_api) = @_;
494    my $func;
495    my $ioctl = bapi_common::version_ioctl $module;
496    my $name;
497
498    print $file <<SWITCH;
499    /* body of ioctl dispatch, convert IOCTL's back to number, that shall help compile to convert switch into the jump table */
500    if ((NEXUS_IOCTL_TYPE(cmd)) != NEXUS_IOCTL_$module\_ID) { BERR_TRACE(-1); goto err_invalid_ioctl;}
501    switch(NEXUS_IOCTL_NUM(cmd)) {
502    default:
503        if(arg==0) {
504            BERR_TRACE(-1);
505            goto err_fault; /* just prevents warning */
506        }
507       BERR_TRACE(-1);
508       goto err_invalid_ioctl;
509SWITCH
510
511
512    print $file case_ioctl($module,$ioctl);
513    print $file "   NEXUS_IOCTL_ENTER(VERSION);\n";
514    print $file "   if (" . bapi_util::call('copy_from_user_small', "&module->args.init", '(void*)arg', "sizeof(module->args.init)") . "!=0) {BERR_TRACE(-1); goto err_fault;}\n";
515    print $file "   if ( module->args.init.version !=" . (bapi_common::version_value $version) . " ) {BERR_TRACE(-1);goto err_version;}\n";
516    print $file "   NEXUS_IOCTL_LEAVE(VERSION);\n";
517    print $file "   break;\n\n";
518
519    for $func (@$funcs) {
520        my $params = $func->{PARAMS};
521        my $param;
522        my $ioctl = bapi_common::ioctl_name $module, $func;
523        my $args = "module->args.$func->{FUNCNAME}";
524                my $retval = "$args.ioctl.__retval";
525        my $attr = bapi_common::process_function_attributes $func, $structs, $funcs;
526        my $class_code = generate_class_code $classes, $func, $args;
527        my ($class_verification,$bypass) = generate_class_verification $classes, $structs, $func, $args, $class_handles, $untrusted_api;
528       
529        next if(exists $func->{ATTR}->{'local'});
530
531        print $file case_ioctl($module,$ioctl);
532        print $file "   NEXUS_IOCTL_ENTER($func->{FUNCNAME});\n";
533        if (!$func->{NOSTRUCT}) {
534            # copy IOCTL parameters
535            print $file "   if (" . bapi_util::call('copy_from_user_small', "&$args.ioctl", '(void*)arg', "sizeof($args.ioctl)") . "!=0) {BERR_TRACE(-1);goto err_fault;}\n";
536           
537            bapi_util::print_code $file, $attr->{driver_pre_call}, "   ";
538           
539            # TODO: must do class_verification before driver_pre_call to avoid leaks if not verified.
540            # solution is to push generate_class_verification logic into driver_pre_call.
541            bapi_util::print_code $file, $class_verification, "   ";
542        }
543   
544        if (!defined $bypass) {
545            # make a function call
546           
547            if ($func->{RETTYPE} ne "void") {
548                print $file "   $retval = \n"
549            }
550           
551            # capture arguments
552            my @args;
553            for $param (@$params) {
554                $name = $param->{NAME};
555   
556                if (exists $attr->{'driver_overwrite'}->{$name}) {
557                    push @args, "\n      $args.$name";
558                } elsif ($param->{ISREF} && $param->{BASETYPE} ne 'void') {
559                    push @args, "\n     ($args.ioctl.$name ? &$args.$name : NULL )";
560                } else {
561                    push @args, "\n      $args.ioctl.$name";
562                }
563            }
564           
565            print $file "   " . bapi_util::call($func->{FUNCNAME}, @args) . ";\n\n";
566        }
567
568        my @post;
569
570        if(defined $attr->{driver_post_success}) {
571            @post = @{$attr->{driver_post_success}};
572        }
573
574        for $param (@$params) {
575            $name = $param->{NAME};
576            # copy OUT parameters
577            next if (exists $attr->{'driver_overwrite'}->{$name});
578            if ($param->{ISREF} && !$param->{INPARAM} && $param->{BASETYPE} ne 'void' ) {
579                # outparams may be NULL
580                push @post, "if ($args.ioctl.$name) {";
581                push @post, "  if (" . bapi_util::call('copy_to_user_small', "$args.ioctl.$name", "&$args.$name", "sizeof($args.$name)") . "!=0) {BERR_TRACE(-1);goto err_fault;}";
582                push @post, "}";
583            }
584        }
585        if( (scalar @post) || (defined $attr->{driver_post_error} || defined($class_code)) ) {
586            if ($func->{RETTYPE} eq "NEXUS_Error") {
587                print $file "  if ($retval == NEXUS_SUCCESS) {\n";
588            } elsif ($func->{RETTYPE} ne "void") {
589                if ($func->{RETTYPE} eq "NEXUS_Timebase" || $func->{RETTYPE} eq "NEXUS_ParserBand")
590                {
591                    print $file "  if ($retval == $func->{RETTYPE}_eInvalid) {\n";
592                    print $file "    $retval = ($func->{RETTYPE})NULL;\n";
593                    print $file "  }\n";
594                }
595                print $file "  if ((void*)$retval != NULL) {\n";
596            } else {
597                print $file "  {\n";
598            }
599            bapi_util::print_code $file, \@post, "     ";
600            bapi_util::print_code $file, $class_code, "     ";
601            if (($func->{RETTYPE} ne "void") && (defined $attr->{driver_post_error}) ) {
602                print $file "  } else { \n";
603                bapi_util::print_code $file, $attr->{driver_post_error}, "     ";
604            }
605            print $file "  }\n";
606        }
607        if ($func->{RETTYPE} ne "void") {
608            # copy only retval other members are left intact
609           print $file "  if (" . bapi_util::call('copy_to_user_small', ('&(( struct ' . ((bapi_common::ioctl_struct $module, $func) . '*)arg)->__retval')),   "&$retval", "sizeof($retval)") . "!=0) {BERR_TRACE(-1);goto err_fault;}\n";
610        }
611        bapi_util::print_code  $file, $attr->{driver_post_always}, "  ";
612        print $file "  NEXUS_IOCTL_LEAVE($func->{FUNCNAME});\n";
613        print $file "  break;\n\n";
614    }
615    print $file " }; /* end of switch */ \n\n\n\n";
616
617}
618
619
620sub generate
621{
622    my ($filename, $module, $version, $structs, $funcs, $class_handles, $untrusted_api) = @_;
623    my $module_lc = lc $module;
624    open FILE, ">$filename";
625    my $file = \*FILE;
626
627    my $destructors = bapi_classes::get_destructors $funcs;
628    my $classes = bapi_classes::get_classes $funcs, $destructors;
629    print $file bapi_util::header $module;
630    print $file "#define NEXUS_DRIVER_MODULE_NAME \"$module\"\n";
631    print $file "#include \"nexus_${module_lc}_module.h\"\n";
632    print $file "BDBG_MODULE(nexus_${module_lc}_driver);\n";
633    print $file "#include \"nexus_core_utils.h\"\n";
634    print $file "#include \"nexus_class_verification.h\"\n";
635    print $file "\n\n";
636    print $file "/* defines to make all module symbols uniques */\n";
637    print $file "#define nexus_driver_module_ioctl nexus_driver_${module_lc}_ioctl\n";
638    print $file "#define nexus_driver_module_open nexus_driver_${module_lc}_open\n";
639    print $file "#define nexus_driver_module_close nexus_driver_${module_lc}_close\n";
640    print $file "#define nexus_driver_module_state nexus_driver_${module_lc}_state\n";
641    print $file "#define nexus_driver_module_args nexus_driver_${module_lc}_args\n";
642    print $file "\n\n";
643    if(scalar @$classes) {
644        print $file "#define NEXUS_DRIVER_MODULE_CLASS_TABLE    nexus_driver_$module\_class_table\n";
645    }
646    print $file "\n\n";
647
648    print $file "#include \"driver/nexus_driver_prologue.h\"\n";
649
650    print $file "#include \"" . (bapi_common::ioctl_header $module) . "\"\n";
651    print $file "\n\n\n";
652    generate_union $file, $module, $funcs, $structs;
653    print $file "\n\n\n";
654    bapi_classes::generate_class_table $file, $classes;
655    print $file "\n\n\n";
656    print $file "#include \"driver/nexus_driver_body.h\"\n";
657    print $file "\n\n\n";
658    generate_ioctl $file, $module, $version, $structs, $classes, $funcs, $class_handles, $untrusted_api;
659    print $file "\n\n\n";
660    print $file "#include \"driver/nexus_driver_epilogue.h\"\n";
661    print $file "\n\n\n";
662    bapi_classes::generate_class_verify_functions $file, $classes, $module;
663    print $file "\n\n\n";
664    close FILE;
665}
666
6671;
668
Note: See TracBrowser for help on using the repository browser.