From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mailman by lists.gnu.org with archive (Exim 4.43) id 1KQ9AC-0002fo-Dj for mharc-grub-devel@gnu.org; Mon, 04 Aug 2008 19:08:28 -0400 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1KQ9AA-0002cc-Cy for grub-devel@gnu.org; Mon, 04 Aug 2008 19:08:26 -0400 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1KQ9A7-0002WW-GY for grub-devel@gnu.org; Mon, 04 Aug 2008 19:08:25 -0400 Received: from [199.232.76.173] (port=38472 helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1KQ9A7-0002WA-A6 for grub-devel@gnu.org; Mon, 04 Aug 2008 19:08:23 -0400 Received: from nf-out-0910.google.com ([64.233.182.187]:38184) by monty-python.gnu.org with esmtp (Exim 4.60) (envelope-from ) id 1KQ9A4-0004XC-KR for grub-devel@gnu.org; Mon, 04 Aug 2008 19:08:23 -0400 Received: by nf-out-0910.google.com with SMTP id c7so839112nfi.26 for ; Mon, 04 Aug 2008 16:08:16 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=domainkey-signature:received:received:subject:from:to:in-reply-to :references:content-type:date:message-id:mime-version:x-mailer; bh=iZEmIUx44qNLlyqlhgajbZrwqUdAecsfmmhDHy/lB+0=; b=Rn8od4DxNcBDzzFHfTxiVDsJVEf9+NiRgliNl5qrkczg4W9bjavDnz/vEp271zwRfb /M/Ok5gSU4IB8e6g5vr4OSI5S8KytjZVppmM92Uok36cgIRypFuhb13foJYPx6ug2Vqd /G7Vuvck8D6WY6hyfodaJ+yPCSn0Tlsel53B4= DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=subject:from:to:in-reply-to:references:content-type:date:message-id :mime-version:x-mailer; b=j+O2Fb+YfqJVgqvjjUAqWH3pXsCHwQJjJJwQ5L9zhaYM+pyyIxYReK2D4IzOdWQRtu wSoybJB2AvbzS6FzJcP2Qldgagq0kXmq+V4JW6IOJwSeGJ7dXdPolSXFxi+TDLPu7xxe GJIaBSZazpc2dWkLJkH2m31e5ihshahB0DzUA= Received: by 10.210.16.16 with SMTP id 16mr369257ebp.7.1217891296005; Mon, 04 Aug 2008 16:08:16 -0700 (PDT) Received: from ?192.168.1.100? ( [213.37.137.93]) by mx.google.com with ESMTPS id z37sm16284551ikz.6.2008.08.04.16.08.09 (version=SSLv3 cipher=RC4-MD5); Mon, 04 Aug 2008 16:08:13 -0700 (PDT) From: Javier =?ISO-8859-1?Q?Mart=EDn?= To: The development of GRUB 2 In-Reply-To: <87iqug33m9.fsf@xs4all.nl> References: <1215137528.26019.58.camel@localhost> <87bq0sibu0.fsf@xs4all.nl> <1216601741.8334.122.camel@localhost> <877ib1khe9.fsf@xs4all.nl> <1217806150.9634.24.camel@localhost> <87iqug33m9.fsf@xs4all.nl> Content-Type: multipart/signed; micalg=pgp-sha1; protocol="application/pgp-signature"; boundary="=-7G2BXokK2O8wQUsdcvNa" Date: Tue, 05 Aug 2008 01:10:25 +0200 Message-Id: <1217891426.15145.38.camel@localhost> Mime-Version: 1.0 X-Mailer: Evolution 2.22.3.1 X-detected-kernel: by monty-python.gnu.org: Linux 2.6 (newer, 2) Subject: Re: [PATCH] Drivemap module X-BeenThere: grub-devel@gnu.org X-Mailman-Version: 2.1.5 Precedence: list Reply-To: The development of GRUB 2 List-Id: The development of GRUB 2 List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 04 Aug 2008 23:08:26 -0000 --=-7G2BXokK2O8wQUsdcvNa Content-Type: multipart/mixed; boundary="=-sKBwnpaU3EMF11q+6YxZ" --=-sKBwnpaU3EMF11q+6YxZ Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable Hi there, El lun, 04-08-2008 a las 22:51 +0200, Marco Gerards escribi=C3=B3: > Javier Mart=C3=ADn writes: >=20 > > After your latest replay, I "reevaluated" my stubbornness WRT some of > > your advices, and I've changed a few things: > > > > - Variables are now declared (and, if possible, initialized) before > > precondition checks, even simple ones. The install_int13_handler > > function has not been modified, however, since I find it a bit > > nonsensical to put bunch of declarations without an obvious meaning jus= t > > after the "else" line: > > grub_uint32_t *ivtslot; > > grub_uint16_t *bpa_freekb; > > grub_size_t total_size; > > grub_uint16_t payload_sizekb; > > grub_uint8_t *handler_base; > > int13map_node_t *handler_map; > > grub_uint32_t ivtentry; >=20 > Please understand me correctly. Code just has to be written according > to our coding standards before it can and will be included. We can > discuss things endlessly but we will simply stick to the GNU Coding > Standards as you might expect. >=20 > I hope you can appreciate that all code of GRUB has the same coding > style, if you like this style or not. Big sigh. Function modified to conform to your preciousss coding style. I might look a bit childish or arrogant saying this, but what is the point upholding a coding style that, no matter how consistent it is, hinders readability. With so much local variables, they are hard to keep track of no matter the coding style, but with the old ("mixed, heretic") style there was not need for a comment before each declaration: they were declared and used when needed instead of at the start of a block, because that function is inherently linear, not block-structured. >=20 > > - Only one declaration per line: even though C is a bit absurd in not > > recognizing T* as a first class type and instead thinking of * as a > > qualifier to the variable name; and even though my code does not incur > > into such ambiguities. > > - Comments moved as you required, reworded as needed > > - Extensive printf showing quasi-help in the "show" mode trimmed down t= o > > just the first sentence. > > - Internal helper functions now use the standard error handling, i.e. > > return grub_error (err, fmt, ...) > > - Comment about the strange "void" type instead of "void*" rephrased to > > be clearer >=20 > Thanks a lot! >=20 > > There is, however, one point in which I keep my objection: comparisons > > between a variable and a constant should be of the form CONSTANT =3D=3D > > variable and not in the reverse order, since an erroneous but quite > > possible change of =3D=3D for =3D results in a compile-time error inste= ad of a > > _extremely_ difficult to trace runtime bug. Such kind of bugs are quite > > excruciating to find in userspace applications within an IDE, so I can'= t > > even consider the pain to debug them in a bootloader. >=20 > I understand your concern, nevertheless, can you please change it? You understand my concern, but seemingly do not understand that in order to conform to the Holy Coding Style you are asking me to write code that can become buggy (and with a very hard to trace bug) with a simple deltion! (point: did you notice that last word _without_ a spelling checker? Now try to do so in a multithousand-line program). While tools like `svn diff' can help in these kind of problems, their utility is greatly diminished if the offending change is part of a multi-line change. Besides, sometimes checks like "if (a=3Db)", or more frequently "if (a=3Df())" are intentionally used in C, so the error might become even more difficult to spot and correct. I ask for a deep reflection on this issue: =EF=BB=BFmaybe I'm dead wrong and an arrogant bra= t in my attempt to tackle the Holy GNU Coding Standards, but I'd like to ask input from more people on this. >=20 > > WRT accepting raw BIOS disk numbers, I agree with you in principle, but > > I'm keeping the functionality for now, since I don't quite like the > > "drivemap (hd0) (hd1)" syntax - which device is which?. I'd rather have > > something akin to "drivemap (hd0) (bios:hd1)", but I want to hear the > > opinions of people in this list. >=20 > I personally do not care a lot if BIOS disk numbers are used. > Although I do not see why it is useful. >=20 > As for the syntax, I would prefer something more GRUB2ish, like: >=20 > map --bios=3D(hd0) --os=3D(hd1) I agree. What about "grub" for the source drive instead of "os", with "bios" being the target drive? I mean: drivemap --grub=3D(hd1) --bios=3D(hd0) Would map 0x80 in the BIOS to grub's (hd1) drive which will most likely be BIOS drive 0x81. However, I prefer not to change it right now. Maybe when there are no other issues WRT to this patch we can set on to tackle this one. >=20 > Or so, perhaps the long argument names can be chosen in a more clever > way :-) > > The new version of the patch is attached, and here is my suggested CLog= : > > > > 2008-08-XX Javier Martin >=20 > (newline) >=20 > > =EF=BB=BF* commands/i386/pc/drivemap.c : New file. > > * commands/i386/pc/drivemap_int13h.S : New file. > > =EF=BB=BF* conf/i386-pc.rmk (pkglib_MODULES) : Added drivemap.m= od > > (drivemap_mod_SOURCES) : New variable > > (drivemap_mod_ASFLAGS) : Likewise > > =EF=BB=BF(drivemap_mod_CFLAGS) : Likewise > > =EF=BB=BF(drivemap_mod_LDFLAGS) : Likewise > > =EF=BB=BF* include/grub/loader.h (grub_loader_register_preboot)= : New > > function prototype. Register a new pre-boot handler >=20 > No need how the change is used or why it was added. >=20 > > (grub_loader_unregister_preboot) : Likewise. Unregister handler >=20 > Same here. >=20 > > (grub_preboot_hookid) : New typedef. Registered hook "handle" >=20 > Same here. >=20 > > =EF=BB=BF* kern/loader.c =EF=BB=BF(grub_loader_register_preboot= ) : New function. > > (grub_loader_unregister_preboot) : Likewise. > > (preboot_hooks) : New variable. Linked list of preboot hooks >=20 > Same here. >=20 > > (grub_loader_boot) : Call the list of preboot-hooks before the > > actual loader >=20 > What's the `=EF=BB=BF'? The what? o_O >=20 > Please do not add a space before the ":"=20 Ok, everything corrected. New CL entry: =EF=BB=BF2008-08-XX Javier Martin =EF=BB=BF* commands/i386/pc/drivemap.c: New file. * commands/i386/pc/drivemap_int13h.S: New file. =EF=BB=BF* conf/i386-pc.rmk (pkglib_MODULES): Added drivemap.mod (drivemap_mod_SOURCES): New variable (drivemap_mod_ASFLAGS): Likewise =EF=BB=BF(drivemap_mod_CFLAGS): Likewise =EF=BB=BF(drivemap_mod_LDFLAGS): Likewise =EF=BB=BF* include/grub/loader.h (grub_loader_register_preboot): Ne= w function prototype. (grub_loader_unregister_preboot): Likewise. (grub_preboot_hookid): New typedef. =EF=BB=BF* kern/loader.c =EF=BB=BF(grub_loader_register_preboot): N= ew function. (grub_loader_unregister_preboot): Likewise. (preboot_hooks): New variable. (grub_loader_boot): Call the list of preboot-hooks before the actual loader >=20 >=20 > Some comments can be found below. Can you please fix the code mention > in the review and similar code? I really want the code to be just > like any other GRUB code. Please understand that we have to maintain > this in the future. If everyone would use his own codingstyle, GRUB > would become unmaintainable. >=20 > > Index: commands/i386/pc/drivemap.c > > =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D > > --- commands/i386/pc/drivemap.c (revisi=C3=B3n: 0) > > +++ commands/i386/pc/drivemap.c (revisi=C3=B3n: 0) > > @@ -0,0 +1,417 @@ > > +/* drivemap.c - command to manage the BIOS drive mappings. */ > > +/* > > + * GRUB -- GRand Unified Bootloader > > + * Copyright (C) 2008 Free Software Foundation, Inc. > > + * > > + * GRUB 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. > > + * > > + * GRUB 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 GRUB. If not, see . > > + */ > > + > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > + > > +#define MODNAME "drivemap" > > + > > +static const struct grub_arg_option options[] =3D { > > + {"list", 'l', 0, "show the current mappings", 0, 0}, > > + {"reset", 'r', 0, "reset all mappings to the default values", 0, 0}, > > + {0, 0, 0, 0, 0, 0} > > +}; > > + > > +/* Syms/vars/funcs exported from drivemap_int13h.S - start. */ > > + > > +/* Realmode far ptr =3D 2 * 16b */ > > +extern grub_uint32_t grub_drivemap_int13_oldhandler; > > +/* Size of the section to be copied */ > > +extern grub_uint16_t grub_drivemap_int13_size; > > + > > +/* This type is used for imported assembly labels, takes no storage an= d is only > > + used to take the symbol address with &label. Do NOT put void* here= . */ > > +typedef void grub_symbol_t; > > +extern grub_symbol_t grub_drivemap_int13_handler_base; > > +extern grub_symbol_t grub_drivemap_int13_mapstart; > > + > > +void grub_drivemap_int13_handler (void); >=20 > The lines above belong in a header file. True, but they are used in a single file in the whole project and thus I see it pointless to extract an unneeded header, which would become one more SVN object to track. However, if you insist I will split the header file at once. In particular, I think the grub_symbol_t typedef should go into the "standard" GRUB headers somehow (but not in symbol.h, which is included from assembly files). >=20 > > +/* Syms/vars/funcs exported from drivemap_int13h.S - end. */ > > + > > + > > +static grub_preboot_hookid insthandler_hook; > > + > > +typedef struct drivemap_node > > +{ > > + grub_uint8_t newdrive; > > + grub_uint8_t redirto; > > + struct drivemap_node *next; > > +} drivemap_node_t; > > + > > +static drivemap_node_t *drivemap =3D 0; >=20 > No need to set this to zero. Yes, you said so already, but I wanted to make the initial state very explicit to a future developer, since that variable is checked against zero in several points. Given that the added source size is four bytes and the added binary size is _zero_, is all the fuss really necessary? Notice that I changed the other variable in which you pointed out this issue, because it is not checked against zero anywhere. >=20 > > +static grub_err_t install_int13_handler (void); > > + > > +/* Puts the specified mapping into the table, replacing an existing ma= pping > > + for newdrive or adding a new one if required. */ > > +static grub_err_t > > +drivemap_set (grub_uint8_t newdrive, grub_uint8_t redirto) > > + >=20 > Please do not add a newline here. Oops, sorry. I forgot to remove it when moving the comment >=20 > > +{ > > + drivemap_node_t *mapping =3D 0; > > + drivemap_node_t *search =3D drivemap; > > + while (search) > > + { > > + if (search->newdrive =3D=3D newdrive) > > + { > > + mapping =3D search; > > + break; > > + } > > + search =3D search->next; > > + } > > + > > + =20 > > + /* Check for pre-existing mappings to modify before creating a new o= ne. */ > > + if (mapping) > > + mapping->redirto =3D redirto; > > + else=20 > > + { > > + mapping =3D grub_malloc (sizeof (drivemap_node_t)); > > + if (!mapping) > > + return grub_error (GRUB_ERR_OUT_OF_MEMORY, > > + "cannot allocate map entry, not enough memo= ry"); > > + mapping->newdrive =3D newdrive; > > + mapping->redirto =3D redirto; > > + mapping->next =3D drivemap; > > + drivemap =3D mapping; > > + } > > + return GRUB_ERR_NONE; > > +} > > + > > +/* Removes the mapping for newdrive from the table. If there is no ma= pping, > > + then this function behaves like a no-op on the map. */ > > +static void > > +drivemap_remove (grub_uint8_t newdrive) > > +{ > > + drivemap_node_t *mapping =3D 0; > > + drivemap_node_t *search =3D drivemap; > > + drivemap_node_t *previous =3D 0; > > + while (search) > > + { > > + if (search->newdrive =3D=3D newdrive) > > + { > > + mapping =3D search; > > + break; > > + } > > + previous =3D search; > > + search =3D search->next; > > + } > > + if (mapping) /* Found. */ >=20 > You forgot one. Corrected. Sorry. >=20 > > + { > > + if (previous) > > + previous->next =3D mapping->next; > > + else /* Entry was head of list. */ > > + drivemap =3D mapping->next; > > + grub_free (mapping); > > + } > > +} > > + > > +/* Given a device name, resolves its BIOS disk number and stores it in= the > > + passed location, which should only be trusted if ERR_NONE is return= ed. */ > > +static grub_err_t > > +parse_biosdisk (const char *name, grub_uint8_t *disknum) > > +{ > > + grub_disk_t disk; > > + if (!name || 0 =3D=3D *name) > > + return grub_error (GRUB_ERR_BAD_ARGUMENT, "device name empty"); > > + /* Skip the first ( in (hd0) - disk_open wants just the name. */ > > + if (*name =3D=3D '(') > > + name++; > > + =20 > > + disk =3D grub_disk_open (name); > > + if (!disk) > > + return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "unknown device \"%s\"= ", name); > > + else > > + { > > + const enum grub_disk_dev_id id =3D disk->dev->id; > > + /* The following assignment is only sound if the device is indee= d a > > + biosdisk. The caller must check the return value. */ > > + if (disknum) > > + *disknum =3D disk->id; > > + grub_disk_close (disk); > > + if (GRUB_DISK_DEVICE_BIOSDISK_ID =3D=3D id) > > + return GRUB_ERR_NONE; > > + else return grub_error (GRUB_ERR_BAD_DEVICE, "%s is not a BIOS d= isk", name); > > + } > > +} > > + > > +/* Given a BIOS disk number, returns its GRUB device name if it exists= . > > + For nonexisting BIOS dnums, this function returns ERR_UNKNOWN_DEVIC= E. */ >=20 > This is GRUB_ERR_UNKNOWN_DEVICE I know, I consciously left the GRUB_ part out because 1) it would require the line to be split and 2) that prefix is all over the place. Corrected, however. >=20 > > +static grub_err_t > > +revparse_biosdisk(const grub_uint8_t dnum, const char **output) > > +{ > > + int found =3D 0; > > + auto int find (const char *name); > > + int find (const char *name) > > + { > > + const grub_disk_t disk =3D grub_disk_open (name); > > + if (!disk) > > + return 0; > > + else > > + { > > + if (disk->id =3D=3D dnum && GRUB_DISK_DEVICE_BIOSDISK_ID =3D= =3D disk->dev->id) > > + { > > + found =3D 1; > > + if (output) > > + *output =3D name; > > + } > > + grub_disk_close (disk); > > + return found; > > + } > > + } > > + > > + grub_disk_dev_iterate (find); > > + if (found) > > + return GRUB_ERR_NONE; > > + else return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "BIOS disk %d not f= ound", dnum); >=20 > Please change this. Em... to what? What is the problem? Do you want me to reverse the comparison? i.e. if (!found) { return error; } else { return ok; } >=20 > > +} > > + > > +/* Given a GRUB-like device name and a convenient location, stores the= related > > + BIOS disk number. Accepts devices like \((f|h)dN\), with 0 <=3D N = < 128. */ > > +static grub_err_t > > +tryparse_diskstring (const char *str, grub_uint8_t *output) > > +{ > > + if (!str || 0 =3D=3D *str) > > + goto fail; > > + /* Skip opening paren in order to allow both (hd0) and hd0. */ > > + if (*str =3D=3D '(') > > + str++; > > + if ((str[0] =3D=3D 'f' || str[0] =3D=3D 'h') && str[1] =3D=3D 'd') > > + { > > + grub_uint8_t bios_num =3D (str[0] =3D=3D 'h')? 0x80 : 0x00; > > + grub_errno =3D GRUB_ERR_NONE; > > + unsigned long drivenum =3D grub_strtoul (str + 2, 0, 0); > > + if (grub_errno !=3D GRUB_ERR_NONE || drivenum > 127) > > + /* N not a number or out of range */ > > + goto fail; >=20 > Can you put this between braces, now comment was added. Done. >=20 > > + else > > + { > > + bios_num |=3D drivenum; > > + if (output) > > + *output =3D bios_num; > > + return GRUB_ERR_NONE; > > + } > > + } > > + else goto fail; >=20 > ... What's the problem here? The lack of braces? The goto (as used in the ext2 code)? >=20 > > +fail: > > + return grub_error (GRUB_ERR_BAD_ARGUMENT, "device format \"%s\" inva= lid: must" > > + "be (f|h)dN, with 0 <=3D N < 128", str); > > +} > > + > > +static grub_err_t > > +grub_cmd_drivemap (struct grub_arg_list *state, int argc, char **args) > > +{ > > + if (state[0].set) > > + { > > + /* Show: list mappings. */ > > + if (!drivemap) > > + grub_printf ("No drives have been remapped"); > > + else > > + { > > + grub_printf ("Showing only remapped drives.\n"); > > + grub_printf ("Mapped\tGRUB\n"); > > + drivemap_node_t *curnode =3D drivemap; > > + while (curnode) > > + { > > + const char *dname =3D 0; > > + grub_err_t err =3D revparse_biosdisk (curnode->redirto, = &dname); > > + if (err !=3D GRUB_ERR_NONE) > > + return grub_error (err, "invalid mapping: non-existent= disk" > > + "or not managed by the BIOS"); > > + grub_printf("0x%02x\t%4s\n", curnode->newdrive, dname); > > + curnode =3D curnode->next; > > + } > > + } > > + } > > + else if (state[1].set) > > + { > > + /* Reset: just delete all mappings, freeing their memory. */ > > + drivemap_node_t *curnode =3D drivemap; > > + drivemap_node_t *prevnode =3D 0; > > + while (curnode) > > + { > > + prevnode =3D curnode; > > + curnode =3D curnode->next; > > + grub_free (prevnode); > > + } > > + drivemap =3D 0; > > + } > > + else > > + { > > + /* Neither flag: put mapping */ >=20 > ". */ Done >=20 > > + grub_uint8_t mapfrom =3D 0; > > + grub_uint8_t mapto =3D 0xFF; > > + grub_err_t err; > > + =20 > > + if (argc !=3D 2) > > + return grub_error (GRUB_ERR_BAD_ARGUMENT, "two arguments requi= red"); > > + > > + err =3D parse_biosdisk (args[0], &mapfrom); > > + if (err !=3D GRUB_ERR_NONE) > > + return err; > > + > > + err =3D tryparse_diskstring (args[1], &mapto); > > + if (err !=3D GRUB_ERR_NONE) /* Not a disk string. Maybe a raw nu= m then? */ >=20 > Please move this up. Done. >=20 > > + { =20 > > + grub_errno =3D GRUB_ERR_NONE; > > + unsigned long num =3D grub_strtoul (args[1], 0, 0); > > + if (grub_errno !=3D GRUB_ERR_NONE || num > 0xFF) /* Not a r= aw num or too high. */ > > + return grub_error (grub_errno, > > + "Target specifier must be of the form (f= dN) or " > > + "(hdN), with 0 <=3D N < 128; or a plain = dec/hex " > > + "number between 0 and 255"); > > + else mapto =3D (grub_uint8_t)num; > > + } > > + =20 > > + if (mapto =3D=3D mapfrom) /* Reset to default. */ >=20 > Same here. Done. >=20 > > + { > > + grub_dprintf (MODNAME, "Removing the mapping for %s (%02x)",= args[0], mapfrom); > > + drivemap_remove (mapfrom); > > + } > > + else /* Map. */ >=20 > Please move the comment inside the braces below. Done, and reworded. >=20 > > + { > > + grub_dprintf (MODNAME, "Mapping %s (%02x) to %02x\n", args[0= ], mapfrom, mapto); > > + return drivemap_set ((grub_uint8_t)mapto, mapfrom); > > + } > > + } > > + > > + return GRUB_ERR_NONE; > > +} > > + > > +typedef struct __attribute__ ((packed)) int13map_node > > +{ > > + grub_uint8_t disknum; > > + grub_uint8_t mapto; > > +} int13map_node_t; > > + > > +/* The min amount of mem that must remain free after installing the ha= ndler. > > + 32 KiB is just above 0x7C00-0x7E00, where the bootsector is loaded.= */ > > +#define MIN_FREE_MEM_KB 32 > > +#define INT13H_OFFSET(x) ( ((grub_uint8_t*)(x)) - ((grub_uint8_t*)&gru= b_drivemap_int13_handler_base) ) > > +#define INT13H_REBASE(x) ( (void*) (((grub_uint8_t*)handler_base) + (x= )) ) > > +#define INT13H_TONEWADDR(x) INT13H_REBASE( INT13H_OFFSET( x ) ) > > + > > +/* Int13h handler installer - reserves conventional memory for the han= dler, > > + copies it over and sets the IVT entry for int13h. =20 > > + This code rests on the assumption that GRUB does not activate any k= ind of > > + memory mapping apart from identity paging, since it accesses realmo= de > > + structures by their absolute addresses, like the IVT at 0 or the BD= A at > > + 0x400; and transforms a pmode pointer into a rmode seg:off far ptr.= */ > > +static grub_err_t > > +install_int13_handler (void) > > +{ > > + grub_size_t entries =3D 0; > > + drivemap_node_t *curentry =3D drivemap; > > + while (curentry) /* Count entries to prepare a contiguous map block= . */ >=20 > ... Comment moved up. >=20 > > + { > > + entries++; > > + curentry =3D curentry->next; > > + } > > + if (0 =3D=3D entries) >=20 > I know this is what you prefer, but can you change this nevertheless? I refer to my objection near the top of the post. >=20 > > + { > > + grub_dprintf (MODNAME, "No drives marked as remapped, installati= on of" > > + "an int13h handler is not required."); > > + return GRUB_ERR_NONE; /* No need to install the int13h handler.= */ > > + } > > + else > > + { > > + grub_dprintf (MODNAME, "Installing int13h handler...\n"); > > + grub_uint32_t *ivtslot =3D (grub_uint32_t*)0x0000004c; > > + =20 > > + /* Save the pointer to the old int13h handler. */ > > + grub_drivemap_int13_oldhandler =3D *ivtslot; > > + grub_dprintf (MODNAME, "Old int13 handler at %04x:%04x\n", > > + (grub_drivemap_int13_oldhandler >> 16) & 0x0ffff, > > + grub_drivemap_int13_oldhandler & 0x0ffff); > > + > > + /* Reserve a section of conventional memory as "BIOS memory" for= handler: > > + BDA offset 0x13 contains the top of such memory. */ > > + grub_uint16_t *bpa_freekb =3D (grub_uint16_t*)0x00000413; > > + grub_dprintf (MODNAME, "Top of conventional memory: %u KiB\n", *= bpa_freekb); > > + grub_size_t total_size =3D grub_drivemap_int13_size > > + + (entries + 1) * sizeof(int13map_node_t); > > + grub_uint16_t payload_sizekb =3D (total_size >> 10) + > > + (((total_size % 1024) =3D=3D 0) ? = 0 : 1); > > + if ((*bpa_freekb - payload_sizekb) < MIN_FREE_MEM_KB) > > + return grub_error (GRUB_ERR_OUT_OF_MEMORY, "refusing to instal= l" > > + "int13 handler, not enough free memory afte= r"); > > + grub_dprintf (MODNAME, "Payload is %u b long, reserving %u Kb\n"= , > > + total_size, payload_sizekb); > > + *bpa_freekb -=3D payload_sizekb; > > + > > + /* Copy int13h handler chunk to reserved area. */ > > + grub_uint8_t *handler_base =3D (grub_uint8_t*)(*bpa_freekb << 10= ); > > + grub_dprintf (MODNAME, "Copying int13 handler to: %p\n", handler= _base); > > + grub_memcpy (handler_base, &grub_drivemap_int13_handler_base, > > + grub_drivemap_int13_size); > > + > > + /* Copy the mappings to the reserved area. */ > > + curentry =3D drivemap; > > + grub_size_t i; > > + int13map_node_t *handler_map =3D (int13map_node_t*) > > + INT13H_TONEWADDR (&grub_drivemap_int13_mapstart)= ; > > + grub_dprintf (MODNAME, "Target map at %p, copying mappings...\n"= , handler_map); > > + for (i =3D 0; i < entries && curentry; i++, curentry =3D curentr= y->next) > > + { > > + handler_map[i].disknum =3D curentry->newdrive; > > + handler_map[i].mapto =3D curentry->redirto; > > + grub_dprintf (MODNAME, "\t#%d: 0x%02x <- 0x%02x\n", i, > > + handler_map[i].disknum, handler_map[i].mapto); > > + } > > + /* Signal end-of-map. */ > > + handler_map[i].disknum =3D 0; > > + handler_map[i].mapto =3D 0; > > + grub_dprintf (MODNAME, "\t#%d: 0x%02x <- 0x%02x (end)\n", i, > > + handler_map[i].disknum, handler_map[i].mapto); > > + > > + /* Install our function as the int13h handler in the IVT. */ > > + grub_uint32_t ivtentry =3D ((grub_uint32_t)handler_base) << 12; = /* Segment address. */ > > + ivtentry |=3D (grub_uint16_t) INT13H_OFFSET(grub_drivemap_int13_= handler); > > + grub_dprintf (MODNAME, "New int13 handler IVT pointer: %04x:%04x= \n", > > + (ivtentry >> 16) & 0x0ffff, ivtentry & 0x0ffff); > > + *ivtslot =3D ivtentry; > > + =20 > > + return GRUB_ERR_NONE; > > + } > > +} > > + > > +GRUB_MOD_INIT (drivemap) > > +{ > > + (void) mod; /* Stop warning. */ > > + grub_register_command (MODNAME, grub_cmd_drivemap, > > + GRUB_COMMAND_FLAG_BOTH, > > + MODNAME " -s | -r | (hdX) newdrivenum", > > + "Manage the BIOS drive mappings", options); > > + insthandler_hook =3D grub_loader_register_preboot (&install_int13_ha= ndler, 1); > > +} > > + > > +GRUB_MOD_FINI (drivemap) > > +{ > > + grub_loader_unregister_preboot (insthandler_hook); > > + insthandler_hook =3D 0; > > + grub_unregister_command (MODNAME); > > +} > > + > > Index: commands/i386/pc/drivemap_int13h.S > > =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D > > --- commands/i386/pc/drivemap_int13h.S (revisi=C3=B3n: 0) > > +++ commands/i386/pc/drivemap_int13h.S (revisi=C3=B3n: 0) > > @@ -0,0 +1,118 @@ > > +/* > > + * GRUB -- GRand Unified Bootloader > > + * Copyright (C) 1999,2000,2001,2002,2003,2005,2006,2007,2008 Free So= ftware Foundation, Inc. > > + * > > + * GRUB 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. > > + * > > + * GRUB 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 GRUB. If not, see . > > + */ > > + > > + > > +/* > > + * Note: These functions defined in this file may be called from C. > > + * Be careful of that you must not modify some registers. Quote > > + * from gcc-2.95.2/gcc/config/i386/i386.h: > > + > > + 1 for registers not available across function calls. > > + These must include the FIXED_REGISTERS and also any > > + registers that can be used without being saved. > > + The latter must include the registers where values are returned > > + and the register where structure-value addresses are passed. > > + Aside from that, you can include as many other registers as you lik= e. > > + > > + ax,dx,cx,bx,si,di,bp,sp,st,st1,st2,st3,st4,st5,st6,st7,arg > > +{ 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 } > > + */ > > + > > +/* > > + * Note: GRUB is compiled with the options -mrtd and -mregparm=3D3. > > + * So the first three arguments are passed in %eax, %edx, and %e= cx, > > + * respectively, and if a function has a fixed number of argumen= ts > > + * and the number if greater than three, the function must retur= n > > + * with "ret $N" where N is ((the number of arguments) - 3) * 4. > > + */ > > + > > +#include > > + > > +#define GRUB_DRIVEMAP_INT13H_OFFSET(x) ((x) - grub_drivemap_int13_hand= ler_base) > > + > > +/* Copy starts here. When deployed, this label must be segment-aligned= */ > > +VARIABLE(grub_drivemap_int13_handler_base) > > + > > +VARIABLE(grub_drivemap_int13_oldhandler) > > + .word 0xdead, 0xbeef > > +/* Drivemap module - INT 13h handler - BIOS HD map */ > > +/* We need to use relative addressing, and with CS to top it all, sinc= e we > > + must make as few changes to the registers as possible. IP-relative > > + addressing like on amd64 would make life way easier here. */ > > +.code16 > > +FUNCTION(grub_drivemap_int13_handler) > > + push %bp > > + mov %sp, %bp > > + push %ax /* We'll need it later to determine the used BIOS function= */ > > + > > + /* Map the drive number (always in DL?) */ > > + push %ax > > + push %bx > > + push %si > > + mov $GRUB_DRIVEMAP_INT13H_OFFSET(grub_drivemap_int13_mapstart), %bx > > + xor %si, %si > > +1:movw %cs:(%bx,%si), %ax > > + cmp %ah, %al > > + jz 3f /* DRV=3DDST =3D> map end - drive not remapped, leave DL as-is= */ > > + cmp %dl, %al > > + jz 2f /* Found - drive remapped, modify DL */ > > + add $2, %si > > + jmp 1b /* Not found, but more remaining, loop */ > > +2:mov %ah, %dl > > +3:pop %si > > + pop %bx > > + xchgw %ax, -4(%bp) /* Recover the old AX and save the map entry for = later */ > > + =20 > > + push %bp > > + /* Simulate interrupt call: push flags and do a far call in order to= set > > + the stack the way the old handler expects it so that its iret wor= ks */ > > + push 6(%bp) > > + movw (%bp), %bp /* Restore the caller BP (is this needed and/or sen= sible?) */ > > + lcall *%cs:GRUB_DRIVEMAP_INT13H_OFFSET(grub_drivemap_int13_oldhandle= r) > > + pop %bp /* The pushed flags were removed by iret */ > > + /* Set the saved flags to what the int13h handler returned */ > > + push %ax > > + pushf > > + pop %ax > > + movw %ax, 6(%bp) > > + pop %ax > > + > > + /* Reverse map any returned drive number if the data returned includ= es it. =20 > > + The only func that does this seems to be origAH =3D 0x08, but man= y BIOS > > + refs say retDL =3D # of drives connected. However, the GRUB Lega= cy code > > + treats this as the _drive number_ and "undoes" the remapping. Th= us, > > + this section has been disabled for testing if it's required */ > > +# cmpb $0x08, -1(%bp) /* Caller's AH */ > > +# jne 4f > > +# xchgw %ax, -4(%bp) /* Map entry used */ > > +# cmp %ah, %al /* DRV=3DDST =3D> drive not remapped */ > > +# je 4f > > +# mov %ah, %dl /* Undo remap */ > > + > > +4:mov %bp, %sp > > + pop %bp > > + iret > > +/* This label MUST be at the end of the copied block, since the instal= ler code > > + reserves additional space for mappings at runtime and copies them o= ver it */ > > +.align 2 > > +VARIABLE(grub_drivemap_int13_mapstart) > > +/* Copy stops here */ > > +.code32 > > +VARIABLE(grub_drivemap_int13_size) > > + .word GRUB_DRIVEMAP_INT13H_OFFSET(grub_drivemap_int13_size) > > + > > Index: conf/i386-pc.rmk > > =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D > > --- conf/i386-pc.rmk (revisi=C3=B3n: 1766) > > +++ conf/i386-pc.rmk (copia de trabajo) > > @@ -158,7 +158,7 @@ > > vbe.mod vbetest.mod vbeinfo.mod video.mod gfxterm.mod \ > > videotest.mod play.mod bitmap.mod tga.mod cpuid.mod serial.mod \ > > ata.mod vga.mod memdisk.mod jpeg.mod png.mod pci.mod lspci.mod \ > > - aout.mod _bsd.mod bsd.mod > > + aout.mod _bsd.mod bsd.mod drivemap.mod > > =20 > > # For biosdisk.mod. > > biosdisk_mod_SOURCES =3D disk/i386/pc/biosdisk.c > > @@ -325,4 +325,11 @@ > > bsd_mod_CFLAGS =3D $(COMMON_CFLAGS) > > bsd_mod_LDFLAGS =3D $(COMMON_LDFLAGS) > > =20 > > +# For drivemap.mod. > > +drivemap_mod_SOURCES =3D commands/i386/pc/drivemap.c \ > > + commands/i386/pc/drivemap_int13h.S > > +drivemap_mod_ASFLAGS =3D $(COMMON_ASFLAGS) > > +drivemap_mod_CFLAGS =3D $(COMMON_CFLAGS) > > +drivemap_mod_LDFLAGS =3D $(COMMON_LDFLAGS) > > + > > include $(srcdir)/conf/common.mk > > Index: include/grub/loader.h > > =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D > > --- include/grub/loader.h (revisi=C3=B3n: 1766) > > +++ include/grub/loader.h (copia de trabajo) > > @@ -37,6 +37,22 @@ > > /* Unset current loader, if any. */ > > void EXPORT_FUNC(grub_loader_unset) (void); > > =20 > > +typedef struct hooklist_node *grub_preboot_hookid; > > + > > +/* Register a function to be called before the boot hook. Returns an = id that > > + can be later used to unregister the preboot (i.e. on module unload)= . If > > + abort_on_error is set, the boot sequence will abort if any of the r= egistered > > + functions return anything else than GRUB_ERR_NONE. > > + On error, the return value will compare equal to 0 and the error in= formation > > + will be available in errno and errmsg. However, if the call is suc= cessful > > + those variables are _not_ modified. */ >=20 > No need to mention errmsg, it's internal to GRUB. As for errno (which > is grub_errno, actually) it does not need to be mentioned, otherwise > we would have to do so everywhere. Please capitalize HOOK and > ABORT_ON_ERROR in the comments above. Done. "hook" removed because it referred to the loader module boot function. >=20 > > +grub_preboot_hookid EXPORT_FUNC(grub_loader_register_preboot) > > + (grub_err_t (*hook) (void), int abort_on_error); > > + > > +/* Unregister a preboot hook by the id returned by loader_register_pre= boot. > > + This functions becomes a no-op if no such function is registered */ > > +void EXPORT_FUNC(grub_loader_unregister_preboot) (grub_preboot_hookid = id); > > + > > /* Call the boot hook in current loader. This may or may not return, > > depending on the setting by grub_loader_set. */ >=20 > Nitpick: "loader. This..." Are you a bot? =C2=AC=C2=AC Corrected >=20 > > grub_err_t EXPORT_FUNC(grub_loader_boot) (void); > > Index: kern/loader.c > > =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D > > --- kern/loader.c (revisi=C3=B3n: 1766) > > +++ kern/loader.c (copia de trabajo) > > @@ -61,11 +61,82 @@ > > grub_loader_loaded =3D 0; > > } > > =20 > > +struct hooklist_node > > +{ > > + grub_err_t (*hook) (void); > > + int abort_on_error; > > + struct hooklist_node *next; > > +}; > > + > > +static struct hooklist_node *preboot_hooks =3D 0; > > + > > +grub_preboot_hookid > > +grub_loader_register_preboot(grub_err_t (*hook) (void), int abort_on_e= rror) > > +{ > > + if (!hook) > > + { > > + grub_error (GRUB_ERR_BAD_ARGUMENT, "preboot hook must not be NUL= L"); > > + return 0; > > + } > > + grub_preboot_hookid newentry =3D grub_malloc (sizeof (struct hooklis= t_node)); >=20 > Mixed declarations/code. Oops, sorry. I put most of my attention on drivemap.c (and even then many comments slipped through). Corrected. >=20 > > + if (!newentry) > > + { > > + grub_error (GRUB_ERR_OUT_OF_MEMORY, "cannot alloc a hookinfo str= ucture"); > > + return 0; > > + } > > + else > > + { > > + newentry->hook =3D hook; > > + newentry->abort_on_error =3D abort_on_error; > > + newentry->next =3D preboot_hooks; > > + preboot_hooks =3D newentry; > > + return newentry; > > + } > > +} > > + > > +void > > +grub_loader_unregister_preboot(grub_preboot_hookid id) >=20 > "preboot (grub" Corrected on both functions ;) >=20 > > +{ > > + grub_preboot_hookid entry =3D 0; > > + grub_preboot_hookid search =3D preboot_hooks; > > + grub_preboot_hookid previous =3D 0; > > + > > + if (0 =3D=3D id) > > + return; >=20 > ... ... xD >=20 > > + while (search) > > + { > > + if (search =3D=3D id) > > + { > > + entry =3D search; > > + break; > > + } > > + previous =3D search; > > + search =3D search->next; > > + } > > + if (entry) /* Found */ >=20 > ... Comment removed, was unnecessary. >=20 > > + { > > + if (previous) > > + previous->next =3D entry->next; > > + else preboot_hooks =3D entry->next; /* Entry was head of list */ > > + grub_free (entry); > > + } > > +} > > + > > grub_err_t > > grub_loader_boot (void) > > { > > if (! grub_loader_loaded) > > return grub_error (GRUB_ERR_NO_KERNEL, "no loaded kernel"); > > + =20 > > + grub_preboot_hookid entry =3D preboot_hooks; >=20 > Mixed declarations/code. Moved the whole line up. >=20 > > + while (entry) > > + { > > + grub_err_t possible_error =3D entry->hook(); > > + if (possible_error !=3D GRUB_ERR_NONE && entry->abort_on_error) > > + return possible_error; > > + entry =3D entry->next; > > + } > > =20 > > if (grub_loader_noreturn) > > grub_machine_fini (); > > _______________________________________________ > > Grub-devel mailing list > > Grub-devel@gnu.org > > http://lists.gnu.org/mailman/listinfo/grub-devel >=20 >=20 >=20 > _______________________________________________ > Grub-devel mailing list > Grub-devel@gnu.org > http://lists.gnu.org/mailman/listinfo/grub-devel New version of the patch follows. I must say that the discussion here has become pretty interesting without degrading into flamewarring - who whats to call Mr. Torvalds and Prof. Tanembaum? ^^ --=-sKBwnpaU3EMF11q+6YxZ Content-Disposition: attachment; filename=drivemap.patch.5 Content-Type: text/x-patch; name=drivemap.patch.5; charset=utf-8 Content-Transfer-Encoding: base64 SW5kZXg6IGNvbW1hbmRzL2kzODYvcGMvZHJpdmVtYXAuYw0KPT09PT09PT09PT09PT09PT09PT09 PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQ0KLS0tIGNvbW1h bmRzL2kzODYvcGMvZHJpdmVtYXAuYwkocmV2aXNpw7NuOiAwKQ0KKysrIGNvbW1hbmRzL2kzODYv cGMvZHJpdmVtYXAuYwkocmV2aXNpw7NuOiAwKQ0KQEAgLTAsMCArMSw0MzkgQEANCisvKiBkcml2 ZW1hcC5jIC0gY29tbWFuZCB0byBtYW5hZ2UgdGhlIEJJT1MgZHJpdmUgbWFwcGluZ3MuICAqLw0K Ky8qDQorICogIEdSVUIgIC0tICBHUmFuZCBVbmlmaWVkIEJvb3Rsb2FkZXINCisgKiAgQ29weXJp Z2h0IChDKSAyMDA4ICBGcmVlIFNvZnR3YXJlIEZvdW5kYXRpb24sIEluYy4NCisgKg0KKyAqICBH UlVCIGlzIGZyZWUgc29mdHdhcmU6IHlvdSBjYW4gcmVkaXN0cmlidXRlIGl0IGFuZC9vciBtb2Rp ZnkNCisgKiAgaXQgdW5kZXIgdGhlIHRlcm1zIG9mIHRoZSBHTlUgR2VuZXJhbCBQdWJsaWMgTGlj ZW5zZSBhcyBwdWJsaXNoZWQgYnkNCisgKiAgdGhlIEZyZWUgU29mdHdhcmUgRm91bmRhdGlvbiwg ZWl0aGVyIHZlcnNpb24gMyBvZiB0aGUgTGljZW5zZSwgb3INCisgKiAgKGF0IHlvdXIgb3B0aW9u KSBhbnkgbGF0ZXIgdmVyc2lvbi4NCisgKg0KKyAqICBHUlVCIGlzIGRpc3RyaWJ1dGVkIGluIHRo ZSBob3BlIHRoYXQgaXQgd2lsbCBiZSB1c2VmdWwsDQorICogIGJ1dCBXSVRIT1VUIEFOWSBXQVJS QU5UWTsgd2l0aG91dCBldmVuIHRoZSBpbXBsaWVkIHdhcnJhbnR5IG9mDQorICogIE1FUkNIQU5U QUJJTElUWSBvciBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRS4gIFNlZSB0aGUNCisg KiAgR05VIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgZm9yIG1vcmUgZGV0YWlscy4NCisgKg0KKyAq ICBZb3Ugc2hvdWxkIGhhdmUgcmVjZWl2ZWQgYSBjb3B5IG9mIHRoZSBHTlUgR2VuZXJhbCBQdWJs aWMgTGljZW5zZQ0KKyAqICBhbG9uZyB3aXRoIEdSVUIuICBJZiBub3QsIHNlZSA8aHR0cDovL3d3 dy5nbnUub3JnL2xpY2Vuc2VzLz4uDQorICovDQorDQorI2luY2x1ZGUgPGdydWIvbm9ybWFsLmg+ DQorI2luY2x1ZGUgPGdydWIvZGwuaD4NCisjaW5jbHVkZSA8Z3J1Yi9tbS5oPg0KKyNpbmNsdWRl IDxncnViL21pc2MuaD4NCisjaW5jbHVkZSA8Z3J1Yi9kaXNrLmg+DQorI2luY2x1ZGUgPGdydWIv bG9hZGVyLmg+DQorI2luY2x1ZGUgPGdydWIvbWFjaGluZS9sb2FkZXIuaD4NCisjaW5jbHVkZSA8 Z3J1Yi9tYWNoaW5lL2Jpb3NkaXNrLmg+DQorDQorI2RlZmluZSBNT0ROQU1FICJkcml2ZW1hcCIN CisNCitzdGF0aWMgY29uc3Qgc3RydWN0IGdydWJfYXJnX29wdGlvbiBvcHRpb25zW10gPSB7DQor ICB7Imxpc3QiLCAnbCcsIDAsICJzaG93IHRoZSBjdXJyZW50IG1hcHBpbmdzIiwgMCwgMH0sDQor ICB7InJlc2V0IiwgJ3InLCAwLCAicmVzZXQgYWxsIG1hcHBpbmdzIHRvIHRoZSBkZWZhdWx0IHZh bHVlcyIsIDAsIDB9LA0KKyAgezAsIDAsIDAsIDAsIDAsIDB9DQorfTsNCisNCisvKiBTeW1zL3Zh cnMvZnVuY3MgZXhwb3J0ZWQgZnJvbSBkcml2ZW1hcF9pbnQxM2guUyAtIHN0YXJ0LiAgKi8NCisN CisvKiBSZWFsbW9kZSBmYXIgcHRyID0gMiAqIDE2YiAqLw0KK2V4dGVybiBncnViX3VpbnQzMl90 IGdydWJfZHJpdmVtYXBfaW50MTNfb2xkaGFuZGxlcjsNCisvKiBTaXplIG9mIHRoZSBzZWN0aW9u IHRvIGJlIGNvcGllZCAqLw0KK2V4dGVybiBncnViX3VpbnQxNl90IGdydWJfZHJpdmVtYXBfaW50 MTNfc2l6ZTsNCisNCisvKiBUaGlzIHR5cGUgaXMgdXNlZCBmb3IgaW1wb3J0ZWQgYXNzZW1ibHkg bGFiZWxzLCB0YWtlcyBubyBzdG9yYWdlIGFuZCBpcyBvbmx5DQorICAgdXNlZCB0byB0YWtlIHRo ZSBzeW1ib2wgYWRkcmVzcyB3aXRoICZsYWJlbC4gIERvIE5PVCBwdXQgdm9pZCogaGVyZS4gICov DQordHlwZWRlZiB2b2lkIGdydWJfc3ltYm9sX3Q7DQorZXh0ZXJuIGdydWJfc3ltYm9sX3QgZ3J1 Yl9kcml2ZW1hcF9pbnQxM19oYW5kbGVyX2Jhc2U7DQorZXh0ZXJuIGdydWJfc3ltYm9sX3QgZ3J1 Yl9kcml2ZW1hcF9pbnQxM19tYXBzdGFydDsNCisNCit2b2lkIGdydWJfZHJpdmVtYXBfaW50MTNf aGFuZGxlciAodm9pZCk7DQorDQorLyogU3ltcy92YXJzL2Z1bmNzIGV4cG9ydGVkIGZyb20gZHJp dmVtYXBfaW50MTNoLlMgLSBlbmQuICAqLw0KKw0KKw0KK3N0YXRpYyBncnViX3ByZWJvb3RfaG9v a2lkIGluc3RoYW5kbGVyX2hvb2s7DQorDQordHlwZWRlZiBzdHJ1Y3QgZHJpdmVtYXBfbm9kZQ0K K3sNCisgIGdydWJfdWludDhfdCBuZXdkcml2ZTsNCisgIGdydWJfdWludDhfdCByZWRpcnRvOw0K KyAgc3RydWN0IGRyaXZlbWFwX25vZGUgKm5leHQ7DQorfSBkcml2ZW1hcF9ub2RlX3Q7DQorDQor c3RhdGljIGRyaXZlbWFwX25vZGVfdCAqZHJpdmVtYXAgPSAwOw0KK3N0YXRpYyBncnViX2Vycl90 IGluc3RhbGxfaW50MTNfaGFuZGxlciAodm9pZCk7DQorDQorLyogUHV0cyB0aGUgc3BlY2lmaWVk IG1hcHBpbmcgaW50byB0aGUgdGFibGUsIHJlcGxhY2luZyBhbiBleGlzdGluZyBtYXBwaW5nDQor ICAgZm9yIG5ld2RyaXZlIG9yIGFkZGluZyBhIG5ldyBvbmUgaWYgcmVxdWlyZWQuICAqLw0KK3N0 YXRpYyBncnViX2Vycl90DQorZHJpdmVtYXBfc2V0IChncnViX3VpbnQ4X3QgbmV3ZHJpdmUsIGdy dWJfdWludDhfdCByZWRpcnRvKQ0KK3sNCisgIGRyaXZlbWFwX25vZGVfdCAqbWFwcGluZyA9IDA7 DQorICBkcml2ZW1hcF9ub2RlX3QgKnNlYXJjaCA9IGRyaXZlbWFwOw0KKyAgd2hpbGUgKHNlYXJj aCkNCisgICAgew0KKyAgICAgIGlmIChzZWFyY2gtPm5ld2RyaXZlID09IG5ld2RyaXZlKQ0KKyAg ICAgICAgew0KKyAgICAgICAgICBtYXBwaW5nID0gc2VhcmNoOw0KKyAgICAgICAgICBicmVhazsN CisgICAgICAgIH0NCisgICAgICBzZWFyY2ggPSBzZWFyY2gtPm5leHQ7DQorICAgIH0NCisNCisg IA0KKyAgLyogQ2hlY2sgZm9yIHByZS1leGlzdGluZyBtYXBwaW5ncyB0byBtb2RpZnkgYmVmb3Jl IGNyZWF0aW5nIGEgbmV3IG9uZS4gICovDQorICBpZiAobWFwcGluZykNCisgICAgbWFwcGluZy0+ cmVkaXJ0byA9IHJlZGlydG87DQorICBlbHNlIA0KKyAgICB7DQorICAgICAgbWFwcGluZyA9IGdy dWJfbWFsbG9jIChzaXplb2YgKGRyaXZlbWFwX25vZGVfdCkpOw0KKyAgICAgIGlmICghbWFwcGlu ZykNCisgICAgICAgIHJldHVybiBncnViX2Vycm9yIChHUlVCX0VSUl9PVVRfT0ZfTUVNT1JZLA0K KyAgICAgICAgICAgICAgICAgICAgICAgICAgICJjYW5ub3QgYWxsb2NhdGUgbWFwIGVudHJ5LCBu b3QgZW5vdWdoIG1lbW9yeSIpOw0KKyAgICAgIG1hcHBpbmctPm5ld2RyaXZlID0gbmV3ZHJpdmU7 DQorICAgICAgbWFwcGluZy0+cmVkaXJ0byA9IHJlZGlydG87DQorICAgICAgbWFwcGluZy0+bmV4 dCA9IGRyaXZlbWFwOw0KKyAgICAgIGRyaXZlbWFwID0gbWFwcGluZzsNCisgICAgfQ0KKyAgcmV0 dXJuIEdSVUJfRVJSX05PTkU7DQorfQ0KKw0KKy8qIFJlbW92ZXMgdGhlIG1hcHBpbmcgZm9yIG5l d2RyaXZlIGZyb20gdGhlIHRhYmxlLiAgSWYgdGhlcmUgaXMgbm8gbWFwcGluZywNCisgICB0aGVu IHRoaXMgZnVuY3Rpb24gYmVoYXZlcyBsaWtlIGEgbm8tb3Agb24gdGhlIG1hcC4gICovDQorc3Rh dGljIHZvaWQNCitkcml2ZW1hcF9yZW1vdmUgKGdydWJfdWludDhfdCBuZXdkcml2ZSkNCit7DQor ICBkcml2ZW1hcF9ub2RlX3QgKm1hcHBpbmcgPSAwOw0KKyAgZHJpdmVtYXBfbm9kZV90ICpzZWFy Y2ggPSBkcml2ZW1hcDsNCisgIGRyaXZlbWFwX25vZGVfdCAqcHJldmlvdXMgPSAwOw0KKw0KKyAg d2hpbGUgKHNlYXJjaCkNCisgICAgew0KKyAgICAgIGlmIChzZWFyY2gtPm5ld2RyaXZlID09IG5l d2RyaXZlKQ0KKyAgICAgICAgew0KKyAgICAgICAgICBtYXBwaW5nID0gc2VhcmNoOw0KKyAgICAg ICAgICBicmVhazsNCisgICAgICAgIH0NCisgICAgICBwcmV2aW91cyA9IHNlYXJjaDsNCisgICAg ICBzZWFyY2ggPSBzZWFyY2gtPm5leHQ7DQorICAgIH0NCisNCisgIGlmIChtYXBwaW5nKQ0KKyAg ICB7DQorICAgICAgaWYgKHByZXZpb3VzKQ0KKyAgICAgICAgcHJldmlvdXMtPm5leHQgPSBtYXBw aW5nLT5uZXh0Ow0KKyAgICAgIGVsc2UgLyogRW50cnkgd2FzIGhlYWQgb2YgbGlzdC4gICovDQor ICAgICAgICBkcml2ZW1hcCA9IG1hcHBpbmctPm5leHQ7DQorICAgICAgZ3J1Yl9mcmVlIChtYXBw aW5nKTsNCisgICAgfQ0KK30NCisNCisvKiBHaXZlbiBhIGRldmljZSBuYW1lLCByZXNvbHZlcyBp dHMgQklPUyBkaXNrIG51bWJlciBhbmQgc3RvcmVzIGl0IGluIHRoZQ0KKyAgIHBhc3NlZCBsb2Nh dGlvbiwgd2hpY2ggc2hvdWxkIG9ubHkgYmUgdHJ1c3RlZCBpZiBFUlJfTk9ORSBpcyByZXR1cm5l ZC4gICovDQorc3RhdGljIGdydWJfZXJyX3QNCitwYXJzZV9iaW9zZGlzayAoY29uc3QgY2hhciAq bmFtZSwgZ3J1Yl91aW50OF90ICpkaXNrbnVtKQ0KK3sNCisgIGdydWJfZGlza190IGRpc2s7DQor ICBpZiAoIW5hbWUgfHwgMCA9PSAqbmFtZSkNCisgICAgcmV0dXJuIGdydWJfZXJyb3IgKEdSVUJf RVJSX0JBRF9BUkdVTUVOVCwgImRldmljZSBuYW1lIGVtcHR5Iik7DQorICAvKiBTa2lwIHRoZSBm aXJzdCAoIGluIChoZDApIC0gZGlza19vcGVuIHdhbnRzIGp1c3QgdGhlIG5hbWUuICAqLw0KKyAg aWYgKCpuYW1lID09ICcoJykNCisgICAgbmFtZSsrOw0KKyAgDQorICBkaXNrID0gZ3J1Yl9kaXNr X29wZW4gKG5hbWUpOw0KKyAgaWYgKCFkaXNrKQ0KKyAgICByZXR1cm4gZ3J1Yl9lcnJvciAoR1JV Ql9FUlJfVU5LTk9XTl9ERVZJQ0UsICJ1bmtub3duIGRldmljZSBcIiVzXCIiLCBuYW1lKTsNCisg IGVsc2UNCisgICAgew0KKyAgICAgIGNvbnN0IGVudW0gZ3J1Yl9kaXNrX2Rldl9pZCBpZCA9IGRp c2stPmRldi0+aWQ7DQorICAgICAgLyogVGhlIGZvbGxvd2luZyBhc3NpZ25tZW50IGlzIG9ubHkg c291bmQgaWYgdGhlIGRldmljZSBpcyBpbmRlZWQgYQ0KKyAgICAgICAgIGJpb3NkaXNrLiAgVGhl IGNhbGxlciBtdXN0IGNoZWNrIHRoZSByZXR1cm4gdmFsdWUuICAqLw0KKyAgICAgIGlmIChkaXNr bnVtKQ0KKyAgICAgICAgKmRpc2tudW0gPSBkaXNrLT5pZDsNCisgICAgICBncnViX2Rpc2tfY2xv c2UgKGRpc2spOw0KKyAgICAgIGlmIChHUlVCX0RJU0tfREVWSUNFX0JJT1NESVNLX0lEID09IGlk KQ0KKyAgICAgICAgcmV0dXJuIEdSVUJfRVJSX05PTkU7DQorICAgICAgZWxzZSByZXR1cm4gZ3J1 Yl9lcnJvciAoR1JVQl9FUlJfQkFEX0RFVklDRSwgIiVzIGlzIG5vdCBhIEJJT1MgZGlzayIsIG5h bWUpOw0KKyAgICB9DQorfQ0KKw0KKy8qIEdpdmVuIGEgQklPUyBkaXNrIG51bWJlciwgcmV0dXJu cyBpdHMgR1JVQiBkZXZpY2UgbmFtZSBpZiBpdCBleGlzdHMuDQorICAgRm9yIG5vbmV4aXN0aW5n IEJJT1MgZGlzayBudW1iZXJzLCB0aGlzIGZ1bmN0aW9uIHJldHVybnMNCisgICBHUlVCX0VSUl9V TktOT1dOX0RFVklDRS4gICovDQorc3RhdGljIGdydWJfZXJyX3QNCityZXZwYXJzZV9iaW9zZGlz ayhjb25zdCBncnViX3VpbnQ4X3QgZG51bSwgY29uc3QgY2hhciAqKm91dHB1dCkNCit7DQorICBp bnQgZm91bmQgPSAwOw0KKyAgYXV0byBpbnQgZmluZCAoY29uc3QgY2hhciAqbmFtZSk7DQorICBp bnQgZmluZCAoY29uc3QgY2hhciAqbmFtZSkNCisgIHsNCisgICAgY29uc3QgZ3J1Yl9kaXNrX3Qg ZGlzayA9IGdydWJfZGlza19vcGVuIChuYW1lKTsNCisgICAgaWYgKCFkaXNrKQ0KKyAgICAgIHJl dHVybiAwOw0KKyAgICBlbHNlDQorICAgICAgew0KKyAgICAgICAgaWYgKGRpc2stPmlkID09IGRu dW0gJiYgR1JVQl9ESVNLX0RFVklDRV9CSU9TRElTS19JRCA9PSBkaXNrLT5kZXYtPmlkKQ0KKyAg ICAgICAgICB7DQorICAgICAgICAgICAgZm91bmQgPSAxOw0KKyAgICAgICAgICAgIGlmIChvdXRw dXQpDQorICAgICAgICAgICAgICAqb3V0cHV0ID0gbmFtZTsNCisgICAgICAgICAgfQ0KKyAgICAg ICAgZ3J1Yl9kaXNrX2Nsb3NlIChkaXNrKTsNCisgICAgICAgIHJldHVybiBmb3VuZDsNCisgICAg ICB9DQorICB9DQorDQorICBncnViX2Rpc2tfZGV2X2l0ZXJhdGUgKGZpbmQpOw0KKyAgaWYgKGZv dW5kKQ0KKyAgICByZXR1cm4gR1JVQl9FUlJfTk9ORTsNCisgIGVsc2UgcmV0dXJuIGdydWJfZXJy b3IgKEdSVUJfRVJSX1VOS05PV05fREVWSUNFLCAiQklPUyBkaXNrICUwMnggbm90IGZvdW5kIiwg ZG51bSk7DQorfQ0KKw0KKy8qIEdpdmVuIGEgR1JVQi1saWtlIGRldmljZSBuYW1lIGFuZCBhIGNv bnZlbmllbnQgbG9jYXRpb24sIHN0b3JlcyB0aGUgcmVsYXRlZA0KKyAgIEJJT1MgZGlzayBudW1i ZXIuICBBY2NlcHRzIGRldmljZXMgbGlrZSBcKChmfGgpZE5cKSwgd2l0aCAwIDw9IE4gPCAxMjgu ICAqLw0KK3N0YXRpYyBncnViX2Vycl90DQordHJ5cGFyc2VfZGlza3N0cmluZyAoY29uc3QgY2hh ciAqc3RyLCBncnViX3VpbnQ4X3QgKm91dHB1dCkNCit7DQorICBpZiAoIXN0ciB8fCAwID09ICpz dHIpDQorICAgIGdvdG8gZmFpbDsNCisgIC8qIFNraXAgb3BlbmluZyBwYXJlbiBpbiBvcmRlciB0 byBhbGxvdyBib3RoIChoZDApIGFuZCBoZDAuICAqLw0KKyAgaWYgKCpzdHIgPT0gJygnKQ0KKyAg ICBzdHIrKzsNCisgIGlmICgoc3RyWzBdID09ICdmJyB8fCBzdHJbMF0gPT0gJ2gnKSAmJiBzdHJb MV0gPT0gJ2QnKQ0KKyAgICB7DQorICAgICAgZ3J1Yl91aW50OF90IGJpb3NfbnVtID0gKHN0clsw XSA9PSAnaCcpPyAweDgwIDogMHgwMDsNCisgICAgICBncnViX2Vycm5vID0gR1JVQl9FUlJfTk9O RTsNCisgICAgICB1bnNpZ25lZCBsb25nIGRyaXZlbnVtID0gZ3J1Yl9zdHJ0b3VsIChzdHIgKyAy LCAwLCAwKTsNCisgICAgICBpZiAoZ3J1Yl9lcnJubyAhPSBHUlVCX0VSUl9OT05FIHx8IGRyaXZl bnVtID4gMTI3KQ0KKyAgICAgICAgew0KKyAgICAgICAgICAvKiBOIG5vdCBhIG51bWJlciBvciBv dXQgb2YgcmFuZ2UuICAqLw0KKyAgICAgICAgICBnb3RvIGZhaWw7DQorICAgICAgICB9DQorICAg ICAgZWxzZQ0KKyAgICAgICAgew0KKyAgICAgICAgICBiaW9zX251bSB8PSBkcml2ZW51bTsNCisg ICAgICAgICAgaWYgKG91dHB1dCkNCisgICAgICAgICAgICAqb3V0cHV0ID0gYmlvc19udW07DQor ICAgICAgICAgIHJldHVybiBHUlVCX0VSUl9OT05FOw0KKyAgICAgICAgfQ0KKyAgICB9DQorICBl bHNlIGdvdG8gZmFpbDsNCisNCitmYWlsOg0KKyAgcmV0dXJuIGdydWJfZXJyb3IgKEdSVUJfRVJS X0JBRF9BUkdVTUVOVCwgImRldmljZSBmb3JtYXQgXCIlc1wiIGludmFsaWQ6IG11c3QiDQorICAg ICAgICAgICAgICAgICAgICAgImJlIChmfGgpZE4sIHdpdGggMCA8PSBOIDwgMTI4Iiwgc3RyKTsN Cit9DQorDQorc3RhdGljIGdydWJfZXJyX3QNCitncnViX2NtZF9kcml2ZW1hcCAoc3RydWN0IGdy dWJfYXJnX2xpc3QgKnN0YXRlLCBpbnQgYXJnYywgY2hhciAqKmFyZ3MpDQorew0KKyAgaWYgKHN0 YXRlWzBdLnNldCkNCisgICAgew0KKyAgICAgIC8qIFNob3c6IGxpc3QgbWFwcGluZ3MuICAqLw0K KyAgICAgIGlmICghZHJpdmVtYXApDQorICAgICAgICBncnViX3ByaW50ZiAoIk5vIGRyaXZlcyBo YXZlIGJlZW4gcmVtYXBwZWQiKTsNCisgICAgICBlbHNlDQorICAgICAgICB7DQorICAgICAgICAg IGdydWJfcHJpbnRmICgiU2hvd2luZyBvbmx5IHJlbWFwcGVkIGRyaXZlcy5cbiIpOw0KKyAgICAg ICAgICBncnViX3ByaW50ZiAoIk1hcHBlZFx0R1JVQlxuIik7DQorICAgICAgICAgIGRyaXZlbWFw X25vZGVfdCAqY3Vybm9kZSA9IGRyaXZlbWFwOw0KKyAgICAgICAgICB3aGlsZSAoY3Vybm9kZSkN CisgICAgICAgICAgICB7DQorICAgICAgICAgICAgICBjb25zdCBjaGFyICpkbmFtZSA9IDA7DQor ICAgICAgICAgICAgICBncnViX2Vycl90IGVyciA9IHJldnBhcnNlX2Jpb3NkaXNrIChjdXJub2Rl LT5yZWRpcnRvLCAmZG5hbWUpOw0KKyAgICAgICAgICAgICAgaWYgKGVyciAhPSBHUlVCX0VSUl9O T05FKQ0KKyAgICAgICAgICAgICAgICByZXR1cm4gZ3J1Yl9lcnJvciAoZXJyLCAiaW52YWxpZCBt YXBwaW5nOiBub24tZXhpc3RlbnQgZGlzayINCisgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgIm9yIG5vdCBtYW5hZ2VkIGJ5IHRoZSBCSU9TIik7DQorICAgICAgICAgICAg ICBncnViX3ByaW50ZigiMHglMDJ4XHQlNHNcbiIsIGN1cm5vZGUtPm5ld2RyaXZlLCBkbmFtZSk7 DQorICAgICAgICAgICAgICBjdXJub2RlID0gY3Vybm9kZS0+bmV4dDsNCisgICAgICAgICAgICB9 DQorICAgICAgICB9DQorICAgIH0NCisgIGVsc2UgaWYgKHN0YXRlWzFdLnNldCkNCisgICAgew0K KyAgICAgIC8qIFJlc2V0OiBqdXN0IGRlbGV0ZSBhbGwgbWFwcGluZ3MsIGZyZWVpbmcgdGhlaXIg bWVtb3J5LiAgKi8NCisgICAgICBkcml2ZW1hcF9ub2RlX3QgKmN1cm5vZGUgPSBkcml2ZW1hcDsN CisgICAgICBkcml2ZW1hcF9ub2RlX3QgKnByZXZub2RlID0gMDsNCisgICAgICB3aGlsZSAoY3Vy bm9kZSkNCisgICAgICAgIHsNCisgICAgICAgICAgcHJldm5vZGUgPSBjdXJub2RlOw0KKyAgICAg ICAgICBjdXJub2RlID0gY3Vybm9kZS0+bmV4dDsNCisgICAgICAgICAgZ3J1Yl9mcmVlIChwcmV2 bm9kZSk7DQorICAgICAgICB9DQorICAgICAgZHJpdmVtYXAgPSAwOw0KKyAgICB9DQorICBlbHNl DQorICAgIHsNCisgICAgICAvKiBOZWl0aGVyIGZsYWc6IHB1dCBtYXBwaW5nLiAgKi8NCisgICAg ICBncnViX3VpbnQ4X3QgbWFwZnJvbSA9IDA7DQorICAgICAgZ3J1Yl91aW50OF90IG1hcHRvID0g MHhGRjsNCisgICAgICBncnViX2Vycl90IGVycjsNCisgICAgICANCisgICAgICBpZiAoYXJnYyAh PSAyKQ0KKyAgICAgICAgcmV0dXJuIGdydWJfZXJyb3IgKEdSVUJfRVJSX0JBRF9BUkdVTUVOVCwg InR3byBhcmd1bWVudHMgcmVxdWlyZWQiKTsNCisNCisgICAgICBlcnIgPSBwYXJzZV9iaW9zZGlz ayAoYXJnc1swXSwgJm1hcGZyb20pOw0KKyAgICAgIGlmIChlcnIgIT0gR1JVQl9FUlJfTk9ORSkN CisgICAgICAgIHJldHVybiBlcnI7DQorDQorICAgICAgZXJyID0gdHJ5cGFyc2VfZGlza3N0cmlu ZyAoYXJnc1sxXSwgJm1hcHRvKTsNCisgICAgICAvKiBXYXMgdGhhdCBhIGRpc2sgc3RyaW5nPyBJ ZiBub3QsIG1heWJlIGEgcmF3IG51bSB0aGVuPyAgKi8NCisgICAgICBpZiAoZXJyICE9IEdSVUJf RVJSX05PTkUpDQorICAgICAgICB7ICAgIA0KKyAgICAgICAgICBncnViX2Vycm5vID0gR1JVQl9F UlJfTk9ORTsNCisgICAgICAgICAgdW5zaWduZWQgbG9uZyBudW0gPSBncnViX3N0cnRvdWwgKGFy Z3NbMV0sIDAsIDApOw0KKyAgICAgICAgICAvKiBUaGUgaW5wdXQgY291bGQgYmUgb3V0c2lkZSBy YW5nZSwgb3Igbm90IGEgbnVtYmVyIGF0IGFsbC4gICovDQorICAgICAgICAgIGlmIChncnViX2Vy cm5vICE9IEdSVUJfRVJSX05PTkUgfHwgbnVtID4gMHhGRikNCisgICAgICAgICAgICByZXR1cm4g Z3J1Yl9lcnJvciAoZ3J1Yl9lcnJubywNCisgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAi VGFyZ2V0IHNwZWNpZmllciBtdXN0IGJlIG9mIHRoZSBmb3JtIChmZE4pIG9yICINCisgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAiKGhkTiksIHdpdGggMCA8PSBOIDwgMTI4OyBvciBhIHBs YWluIGRlYy9oZXggIg0KKyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJudW1iZXIgYmV0 d2VlbiAwIGFuZCAyNTUiKTsNCisgICAgICAgICAgZWxzZSBtYXB0byA9IChncnViX3VpbnQ4X3Qp bnVtOw0KKyAgICAgICAgfQ0KKyAgICAgIA0KKyAgICAgIGlmIChtYXB0byA9PSBtYXBmcm9tKQ0K KyAgICAgICAgew0KKyAgICAgICAgICAvKiBSZXNldCB0byBkZWZhdWx0LiAgKi8NCisgICAgICAg ICAgZ3J1Yl9kcHJpbnRmIChNT0ROQU1FLCAiUmVtb3ZpbmcgdGhlIG1hcHBpbmcgZm9yICVzICgl MDJ4KSIsIGFyZ3NbMF0sIG1hcGZyb20pOw0KKyAgICAgICAgICBkcml2ZW1hcF9yZW1vdmUgKG1h cGZyb20pOw0KKyAgICAgICAgfQ0KKyAgICAgIGVsc2UNCisgICAgICAgIHsNCisgICAgICAgICAg LyogU2V0IHRoZSBtYXBwaW5nIGZvciB0aGUgZGlzayAob3ZlcndyaXRlcyBhbnkgZXhpc3Rpbmcg bWFwcGluZykuICAqLw0KKyAgICAgICAgICBncnViX2RwcmludGYgKE1PRE5BTUUsICJNYXBwaW5n ICVzICglMDJ4KSB0byAlMDJ4XG4iLCBhcmdzWzBdLCBtYXBmcm9tLCBtYXB0byk7DQorICAgICAg ICAgIHJldHVybiBkcml2ZW1hcF9zZXQgKChncnViX3VpbnQ4X3QpbWFwdG8sIG1hcGZyb20pOw0K KyAgICAgICAgfQ0KKyAgICB9DQorDQorICByZXR1cm4gR1JVQl9FUlJfTk9ORTsNCit9DQorDQor dHlwZWRlZiBzdHJ1Y3QgX19hdHRyaWJ1dGVfXyAoKHBhY2tlZCkpIGludDEzbWFwX25vZGUNCit7 DQorICBncnViX3VpbnQ4X3QgZGlza251bTsNCisgIGdydWJfdWludDhfdCBtYXB0bzsNCit9IGlu dDEzbWFwX25vZGVfdDsNCisNCisvKiBUaGUgbWluIGFtb3VudCBvZiBtZW0gdGhhdCBtdXN0IHJl bWFpbiBmcmVlIGFmdGVyIGluc3RhbGxpbmcgdGhlIGhhbmRsZXIuDQorICAgMzIgS2lCIGlzIGp1 c3QgYWJvdmUgMHg3QzAwLTB4N0UwMCwgd2hlcmUgdGhlIGJvb3RzZWN0b3IgaXMgbG9hZGVkLiAg Ki8NCisjZGVmaW5lIE1JTl9GUkVFX01FTV9LQiAzMg0KKyNkZWZpbmUgSU5UMTNIX09GRlNFVCh4 KSAoICgoZ3J1Yl91aW50OF90KikoeCkpIC0gKChncnViX3VpbnQ4X3QqKSZncnViX2RyaXZlbWFw X2ludDEzX2hhbmRsZXJfYmFzZSkgKQ0KKyNkZWZpbmUgSU5UMTNIX1JFQkFTRSh4KSAoICh2b2lk KikgKCgoZ3J1Yl91aW50OF90KiloYW5kbGVyX2Jhc2UpICsgKHgpKSApDQorI2RlZmluZSBJTlQx M0hfVE9ORVdBRERSKHgpIElOVDEzSF9SRUJBU0UoIElOVDEzSF9PRkZTRVQoIHggKSApDQorDQor LyogSW50MTNoIGhhbmRsZXIgaW5zdGFsbGVyIC0gcmVzZXJ2ZXMgY29udmVudGlvbmFsIG1lbW9y eSBmb3IgdGhlIGhhbmRsZXIsDQorICAgY29waWVzIGl0IG92ZXIgYW5kIHNldHMgdGhlIElWVCBl bnRyeSBmb3IgaW50MTNoLiAgDQorICAgVGhpcyBjb2RlIHJlc3RzIG9uIHRoZSBhc3N1bXB0aW9u IHRoYXQgR1JVQiBkb2VzIG5vdCBhY3RpdmF0ZSBhbnkga2luZCBvZg0KKyAgIG1lbW9yeSBtYXBw aW5nIGFwYXJ0IGZyb20gaWRlbnRpdHkgcGFnaW5nLCBzaW5jZSBpdCBhY2Nlc3NlcyByZWFsbW9k ZQ0KKyAgIHN0cnVjdHVyZXMgYnkgdGhlaXIgYWJzb2x1dGUgYWRkcmVzc2VzLCBsaWtlIHRoZSBJ VlQgYXQgMCBvciB0aGUgQkRBIGF0DQorICAgMHg0MDA7IGFuZCB0cmFuc2Zvcm1zIGEgcG1vZGUg cG9pbnRlciBpbnRvIGEgcm1vZGUgc2VnOm9mZiBmYXIgcHRyLiAgKi8NCitzdGF0aWMgZ3J1Yl9l cnJfdA0KK2luc3RhbGxfaW50MTNfaGFuZGxlciAodm9pZCkNCit7DQorICBncnViX3NpemVfdCBl bnRyaWVzID0gMDsNCisgIGRyaXZlbWFwX25vZGVfdCAqY3VyZW50cnkgPSBkcml2ZW1hcDsNCisg IC8qIENvdW50IGVudHJpZXMgdG8gcHJlcGFyZSBhIGNvbnRpZ3VvdXMgbWFwIGJsb2NrLiAgKi8N CisgIHdoaWxlIChjdXJlbnRyeSkNCisgICAgew0KKyAgICAgIGVudHJpZXMrKzsNCisgICAgICBj dXJlbnRyeSA9IGN1cmVudHJ5LT5uZXh0Ow0KKyAgICB9DQorICBpZiAoMCA9PSBlbnRyaWVzKQ0K KyAgICB7DQorICAgICAgLyogTm8gbmVlZCB0byBpbnN0YWxsIHRoZSBpbnQxM2ggaGFuZGxlci4g ICovDQorICAgICAgZ3J1Yl9kcHJpbnRmIChNT0ROQU1FLCAiTm8gZHJpdmVzIG1hcmtlZCBhcyBy ZW1hcHBlZCwgaW5zdGFsbGF0aW9uIG9mIg0KKyAgICAgICAgICAgICAgICAgICJhbiBpbnQxM2gg aGFuZGxlciBpcyBub3QgcmVxdWlyZWQuIik7DQorICAgICAgcmV0dXJuIEdSVUJfRVJSX05PTkU7 DQorICAgIH0NCisgIGVsc2UNCisgICAgew0KKyAgICAgIC8qIFJlYWwgbW9kZSBJVlQgc2xvdCAo c2VnOm9mZiBmYXIgcG9pbnRlcikgZm9yIGludGVycnVwdCAweDEzLiAgKi8NCisgICAgICBncnVi X3VpbnQzMl90ICppdnRzbG90ID0gKGdydWJfdWludDMyX3QqKTB4MDAwMDAwNGM7DQorICAgICAg LyogQkRBIG9mZnNldCAweDEzIGNvbnRhaW5zIHRoZSB0b3Agb2YgY29udmVudGlvbmFsIG1lbW9y eSwgaW4ga2lCLiAgKi8NCisgICAgICBncnViX3VpbnQxNl90ICpicGFfZnJlZWtiID0gKGdydWJf dWludDE2X3QqKTB4MDAwMDA0MTM7DQorICAgICAgLyogU2l6ZSBvZiB0aGUgZnVsbCBpbnQxMyBo YW5kbGVyICJidW5kbGUiLCBpbmNsdWRpbmcgY29kZSBhbmQgbWFwLiAgKi8NCisgICAgICBncnVi X3NpemVfdCB0b3RhbF9zaXplOw0KKyAgICAgIC8qIFRoZSBmb3JtZXIsIGNlaWwtcm91bmRlZCB0 byBLaUIuICAqLw0KKyAgICAgIGdydWJfdWludDE2X3QgcGF5bG9hZF9zaXpla2I7DQorICAgICAg LyogQmFzZSBhZGRyZXNzIG9mIHRoZSBzcGFjZSByZXNlcnZlZCBmb3IgdGhlIGhhbmRsZXIgYnVu ZGxlLiAgKi8NCisgICAgICBncnViX3VpbnQ4X3QgKmhhbmRsZXJfYmFzZTsNCisgICAgICAvKiBB ZGRyZXNzIG9mIHRoZSBtYXAgd2l0aGluIHRoZSBkZXBsb3llZCBidW5kbGUuICAqLw0KKyAgICAg IGludDEzbWFwX25vZGVfdCAqaGFuZGxlcl9tYXA7DQorICAgICAgLyogUmVhbCBtb2RlIElWVCBl bnRyeSAoc2VnOm9mZiBmYXIgcG9pbnRlcikgZm9yIHRoZSBuZXcgaGFuZGxlci4gICovDQorICAg ICAgZ3J1Yl91aW50MzJfdCBpdnRlbnRyeTsNCisNCisgICAgICBncnViX2RwcmludGYgKE1PRE5B TUUsICJJbnN0YWxsaW5nIGludDEzaCBoYW5kbGVyLi4uXG4iKTsNCisgICAgICANCisgICAgICAv KiBTYXZlIHRoZSBwb2ludGVyIHRvIHRoZSBvbGQgaGFuZGxlci4gICovDQorICAgICAgZ3J1Yl9k cml2ZW1hcF9pbnQxM19vbGRoYW5kbGVyID0gKml2dHNsb3Q7DQorICAgICAgZ3J1Yl9kcHJpbnRm IChNT0ROQU1FLCAiT2xkIGludDEzIGhhbmRsZXIgYXQgJTA0eDolMDR4XG4iLA0KKyAgICAgICAg ICAgICAgICAgIChncnViX2RyaXZlbWFwX2ludDEzX29sZGhhbmRsZXIgPj4gMTYpICYgMHgwZmZm ZiwNCisgICAgICAgICAgICAgICAgICBncnViX2RyaXZlbWFwX2ludDEzX29sZGhhbmRsZXIgJiAw eDBmZmZmKTsNCisNCisgICAgICAvKiBSZXNlcnZlIGEgc2VjdGlvbiBvZiBjb252ZW50aW9uYWwg bWVtb3J5IGFzICJCSU9TIG1lbW9yeSIgZm9yIGhhbmRsZXIuICAqLw0KKyAgICAgIGdydWJfZHBy aW50ZiAoTU9ETkFNRSwgIlRvcCBvZiBjb252ZW50aW9uYWwgbWVtb3J5OiAldSBLaUJcbiIsICpi cGFfZnJlZWtiKTsNCisgICAgICB0b3RhbF9zaXplID0gZ3J1Yl9kcml2ZW1hcF9pbnQxM19zaXpl DQorICAgICAgICAgICAgICAgICAgICsgKGVudHJpZXMgKyAxKSAqIHNpemVvZihpbnQxM21hcF9u b2RlX3QpOw0KKyAgICAgIHBheWxvYWRfc2l6ZWtiID0gKHRvdGFsX3NpemUgPj4gMTApICsNCisg ICAgICAgICAgICAgICAgICAgICAgICgoKHRvdGFsX3NpemUgJSAxMDI0KSA9PSAwKSA/IDAgOiAx KTsNCisgICAgICBpZiAoKCpicGFfZnJlZWtiIC0gcGF5bG9hZF9zaXpla2IpIDwgTUlOX0ZSRUVf TUVNX0tCKQ0KKyAgICAgICAgcmV0dXJuIGdydWJfZXJyb3IgKEdSVUJfRVJSX09VVF9PRl9NRU1P UlksICJyZWZ1c2luZyB0byBpbnN0YWxsIg0KKyAgICAgICAgICAgICAgICAgICAgICAgICAgICJp bnQxMyBoYW5kbGVyLCBub3QgZW5vdWdoIGZyZWUgbWVtb3J5IGFmdGVyIik7DQorICAgICAgZ3J1 Yl9kcHJpbnRmIChNT0ROQU1FLCAiUGF5bG9hZCBpcyAldSBiIGxvbmcsIHJlc2VydmluZyAldSBL YlxuIiwNCisJCQkJCXRvdGFsX3NpemUsIHBheWxvYWRfc2l6ZWtiKTsNCisgICAgICAqYnBhX2Zy ZWVrYiAtPSBwYXlsb2FkX3NpemVrYjsNCisNCisgICAgICAvKiBDb3B5IGludDEzaCBoYW5kbGVy IGJ1bmRsZSB0byByZXNlcnZlZCBhcmVhLiAgKi8NCisgICAgICBoYW5kbGVyX2Jhc2UgPSAoZ3J1 Yl91aW50OF90KikoKmJwYV9mcmVla2IgPDwgMTApOw0KKyAgICAgIGdydWJfZHByaW50ZiAoTU9E TkFNRSwgIkNvcHlpbmcgaW50MTMgaGFuZGxlciB0bzogJXBcbiIsIGhhbmRsZXJfYmFzZSk7DQor ICAgICAgZ3J1Yl9tZW1jcHkgKGhhbmRsZXJfYmFzZSwgJmdydWJfZHJpdmVtYXBfaW50MTNfaGFu ZGxlcl9iYXNlLA0KKyAgICAgICAgICAgICAgICAgICBncnViX2RyaXZlbWFwX2ludDEzX3NpemUp Ow0KKw0KKyAgICAgIC8qIENvcHkgdGhlIG1hcHBpbmdzIHRvIHRoZSByZXNlcnZlZCBhcmVhLiAg Ki8NCisgICAgICBjdXJlbnRyeSA9IGRyaXZlbWFwOw0KKyAgICAgIGdydWJfc2l6ZV90IGk7DQor ICAgICAgaGFuZGxlcl9tYXAgPSAoaW50MTNtYXBfbm9kZV90KikNCisgICAgICAgICAgICAgICAg ICAgIElOVDEzSF9UT05FV0FERFIgKCZncnViX2RyaXZlbWFwX2ludDEzX21hcHN0YXJ0KTsNCisg ICAgICBncnViX2RwcmludGYgKE1PRE5BTUUsICJUYXJnZXQgbWFwIGF0ICVwLCBjb3B5aW5nIG1h cHBpbmdzLi4uXG4iLCBoYW5kbGVyX21hcCk7DQorICAgICAgZm9yIChpID0gMDsgaSA8IGVudHJp ZXMgJiYgY3VyZW50cnk7IGkrKywgY3VyZW50cnkgPSBjdXJlbnRyeS0+bmV4dCkNCisgICAgICAg IHsNCisgICAgICAgICAgaGFuZGxlcl9tYXBbaV0uZGlza251bSA9IGN1cmVudHJ5LT5uZXdkcml2 ZTsNCisgICAgICAgICAgaGFuZGxlcl9tYXBbaV0ubWFwdG8gPSBjdXJlbnRyeS0+cmVkaXJ0bzsN CisgICAgICAgICAgZ3J1Yl9kcHJpbnRmIChNT0ROQU1FLCAiXHQjJWQ6IDB4JTAyeCA8LSAweCUw MnhcbiIsIGksDQorCQkJCQkJaGFuZGxlcl9tYXBbaV0uZGlza251bSwgaGFuZGxlcl9tYXBbaV0u bWFwdG8pOw0KKyAgICAgICAgfQ0KKyAgICAgIC8qIFNpZ25hbCBlbmQtb2YtbWFwLiAgKi8NCisg ICAgICBoYW5kbGVyX21hcFtpXS5kaXNrbnVtID0gMDsNCisgICAgICBoYW5kbGVyX21hcFtpXS5t YXB0byA9IDA7DQorICAgICAgZ3J1Yl9kcHJpbnRmIChNT0ROQU1FLCAiXHQjJWQ6IDB4JTAyeCA8 LSAweCUwMnggKGVuZClcbiIsIGksDQorCQkJCQloYW5kbGVyX21hcFtpXS5kaXNrbnVtLCBoYW5k bGVyX21hcFtpXS5tYXB0byk7DQorDQorICAgICAgLyogSW5zdGFsbCBvdXIgZnVuY3Rpb24gYXMg dGhlIGludDEzaCBoYW5kbGVyIGluIHRoZSBJVlQuICAqLw0KKyAgICAgIGl2dGVudHJ5ID0gKChn cnViX3VpbnQzMl90KWhhbmRsZXJfYmFzZSkgPDwgMTI7IC8qIFNlZ21lbnQgYWRkcmVzcy4gICov DQorICAgICAgaXZ0ZW50cnkgfD0gKGdydWJfdWludDE2X3QpIElOVDEzSF9PRkZTRVQoZ3J1Yl9k cml2ZW1hcF9pbnQxM19oYW5kbGVyKTsNCisgICAgICBncnViX2RwcmludGYgKE1PRE5BTUUsICJO ZXcgaW50MTMgaGFuZGxlciBJVlQgcG9pbnRlcjogJTA0eDolMDR4XG4iLA0KKyAgICAgICAgICAg ICAgICAgIChpdnRlbnRyeSA+PiAxNikgJiAweDBmZmZmLCBpdnRlbnRyeSAmIDB4MGZmZmYpOw0K KyAgICAgICppdnRzbG90ID0gaXZ0ZW50cnk7DQorICAgICAgDQorICAgICAgcmV0dXJuIEdSVUJf RVJSX05PTkU7DQorICAgIH0NCit9DQorDQorR1JVQl9NT0RfSU5JVCAoZHJpdmVtYXApDQorew0K KyAgKHZvaWQpIG1vZDsJCQkvKiBTdG9wIHdhcm5pbmcuICAqLw0KKyAgZ3J1Yl9yZWdpc3Rlcl9j b21tYW5kIChNT0ROQU1FLCBncnViX2NtZF9kcml2ZW1hcCwNCisgICAgICAgICAgICAgICAgICAg ICAgICAgR1JVQl9DT01NQU5EX0ZMQUdfQk9USCwNCisJCQkgICAgICAgICAgICAgICAgICAgTU9E TkFNRSAiIC1zIHwgLXIgfCAoaGRYKSBuZXdkcml2ZW51bSIsDQorICAgICAgICAgICAgICAgICAg ICAgICAgICJNYW5hZ2UgdGhlIEJJT1MgZHJpdmUgbWFwcGluZ3MiLCBvcHRpb25zKTsNCisgIGlu c3RoYW5kbGVyX2hvb2sgPSBncnViX2xvYWRlcl9yZWdpc3Rlcl9wcmVib290ICgmaW5zdGFsbF9p bnQxM19oYW5kbGVyLCAxKTsNCit9DQorDQorR1JVQl9NT0RfRklOSSAoZHJpdmVtYXApDQorew0K KyAgZ3J1Yl9sb2FkZXJfdW5yZWdpc3Rlcl9wcmVib290IChpbnN0aGFuZGxlcl9ob29rKTsNCisg IGluc3RoYW5kbGVyX2hvb2sgPSAwOw0KKyAgZ3J1Yl91bnJlZ2lzdGVyX2NvbW1hbmQgKE1PRE5B TUUpOw0KK30NCisNCkluZGV4OiBjb21tYW5kcy9pMzg2L3BjL2RyaXZlbWFwX2ludDEzaC5TDQo9 PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09 PT09PT09PT09DQotLS0gY29tbWFuZHMvaTM4Ni9wYy9kcml2ZW1hcF9pbnQxM2guUwkocmV2aXNp w7NuOiAwKQ0KKysrIGNvbW1hbmRzL2kzODYvcGMvZHJpdmVtYXBfaW50MTNoLlMJKHJldmlzacOz bjogMCkNCkBAIC0wLDAgKzEsMTE4IEBADQorLyoNCisgKiAgR1JVQiAgLS0gIEdSYW5kIFVuaWZp ZWQgQm9vdGxvYWRlcg0KKyAqICBDb3B5cmlnaHQgKEMpIDE5OTksMjAwMCwyMDAxLDIwMDIsMjAw MywyMDA1LDIwMDYsMjAwNywyMDA4IEZyZWUgU29mdHdhcmUgRm91bmRhdGlvbiwgSW5jLg0KKyAq DQorICogIEdSVUIgaXMgZnJlZSBzb2Z0d2FyZTogeW91IGNhbiByZWRpc3RyaWJ1dGUgaXQgYW5k L29yIG1vZGlmeQ0KKyAqICBpdCB1bmRlciB0aGUgdGVybXMgb2YgdGhlIEdOVSBHZW5lcmFsIFB1 YmxpYyBMaWNlbnNlIGFzIHB1Ymxpc2hlZCBieQ0KKyAqICB0aGUgRnJlZSBTb2Z0d2FyZSBGb3Vu ZGF0aW9uLCBlaXRoZXIgdmVyc2lvbiAzIG9mIHRoZSBMaWNlbnNlLCBvcg0KKyAqICAoYXQgeW91 ciBvcHRpb24pIGFueSBsYXRlciB2ZXJzaW9uLg0KKyAqDQorICogIEdSVUIgaXMgZGlzdHJpYnV0 ZWQgaW4gdGhlIGhvcGUgdGhhdCBpdCB3aWxsIGJlIHVzZWZ1bCwNCisgKiAgYnV0IFdJVEhPVVQg QU5ZIFdBUlJBTlRZOyB3aXRob3V0IGV2ZW4gdGhlIGltcGxpZWQgd2FycmFudHkgb2YNCisgKiAg TUVSQ0hBTlRBQklMSVRZIG9yIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFLiAgU2Vl IHRoZQ0KKyAqICBHTlUgR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBmb3IgbW9yZSBkZXRhaWxzLg0K KyAqDQorICogIFlvdSBzaG91bGQgaGF2ZSByZWNlaXZlZCBhIGNvcHkgb2YgdGhlIEdOVSBHZW5l cmFsIFB1YmxpYyBMaWNlbnNlDQorICogIGFsb25nIHdpdGggR1JVQi4gIElmIG5vdCwgc2VlIDxo dHRwOi8vd3d3LmdudS5vcmcvbGljZW5zZXMvPi4NCisgKi8NCisNCisNCisvKg0KKyAqIE5vdGU6 IFRoZXNlIGZ1bmN0aW9ucyBkZWZpbmVkIGluIHRoaXMgZmlsZSBtYXkgYmUgY2FsbGVkIGZyb20g Qy4NCisgKiAgICAgICBCZSBjYXJlZnVsIG9mIHRoYXQgeW91IG11c3Qgbm90IG1vZGlmeSBzb21l IHJlZ2lzdGVycy4gUXVvdGUNCisgKiAgICAgICBmcm9tIGdjYy0yLjk1LjIvZ2NjL2NvbmZpZy9p Mzg2L2kzODYuaDoNCisNCisgICAxIGZvciByZWdpc3RlcnMgbm90IGF2YWlsYWJsZSBhY3Jvc3Mg ZnVuY3Rpb24gY2FsbHMuDQorICAgVGhlc2UgbXVzdCBpbmNsdWRlIHRoZSBGSVhFRF9SRUdJU1RF UlMgYW5kIGFsc28gYW55DQorICAgcmVnaXN0ZXJzIHRoYXQgY2FuIGJlIHVzZWQgd2l0aG91dCBi ZWluZyBzYXZlZC4NCisgICBUaGUgbGF0dGVyIG11c3QgaW5jbHVkZSB0aGUgcmVnaXN0ZXJzIHdo ZXJlIHZhbHVlcyBhcmUgcmV0dXJuZWQNCisgICBhbmQgdGhlIHJlZ2lzdGVyIHdoZXJlIHN0cnVj dHVyZS12YWx1ZSBhZGRyZXNzZXMgYXJlIHBhc3NlZC4NCisgICBBc2lkZSBmcm9tIHRoYXQsIHlv dSBjYW4gaW5jbHVkZSBhcyBtYW55IG90aGVyIHJlZ2lzdGVycyBhcyB5b3UgbGlrZS4NCisNCisg IGF4LGR4LGN4LGJ4LHNpLGRpLGJwLHNwLHN0LHN0MSxzdDIsc3QzLHN0NCxzdDUsc3Q2LHN0Nyxh cmcNCit7ICAxLCAxLCAxLCAwLCAwLCAwLCAwLCAxLCAxLCAgMSwgIDEsICAxLCAgMSwgIDEsICAx LCAgMSwgIDEgfQ0KKyAqLw0KKw0KKy8qDQorICogTm90ZTogR1JVQiBpcyBjb21waWxlZCB3aXRo IHRoZSBvcHRpb25zIC1tcnRkIGFuZCAtbXJlZ3Bhcm09My4NCisgKiAgICAgICBTbyB0aGUgZmly c3QgdGhyZWUgYXJndW1lbnRzIGFyZSBwYXNzZWQgaW4gJWVheCwgJWVkeCwgYW5kICVlY3gsDQor ICogICAgICAgcmVzcGVjdGl2ZWx5LCBhbmQgaWYgYSBmdW5jdGlvbiBoYXMgYSBmaXhlZCBudW1i ZXIgb2YgYXJndW1lbnRzDQorICogICAgICAgYW5kIHRoZSBudW1iZXIgaWYgZ3JlYXRlciB0aGFu IHRocmVlLCB0aGUgZnVuY3Rpb24gbXVzdCByZXR1cm4NCisgKiAgICAgICB3aXRoICJyZXQgJE4i IHdoZXJlIE4gaXMgKCh0aGUgbnVtYmVyIG9mIGFyZ3VtZW50cykgLSAzKSAqIDQuDQorICovDQor DQorI2luY2x1ZGUgPGdydWIvc3ltYm9sLmg+DQorDQorI2RlZmluZSBHUlVCX0RSSVZFTUFQX0lO VDEzSF9PRkZTRVQoeCkgKCh4KSAtIGdydWJfZHJpdmVtYXBfaW50MTNfaGFuZGxlcl9iYXNlKQ0K Kw0KKy8qIENvcHkgc3RhcnRzIGhlcmUuIFdoZW4gZGVwbG95ZWQsIHRoaXMgbGFiZWwgbXVzdCBi ZSBzZWdtZW50LWFsaWduZWQgKi8NCitWQVJJQUJMRShncnViX2RyaXZlbWFwX2ludDEzX2hhbmRs ZXJfYmFzZSkNCisNCitWQVJJQUJMRShncnViX2RyaXZlbWFwX2ludDEzX29sZGhhbmRsZXIpDQor ICAud29yZCAweGRlYWQsIDB4YmVlZg0KKy8qIERyaXZlbWFwIG1vZHVsZSAtIElOVCAxM2ggaGFu ZGxlciAtIEJJT1MgSEQgbWFwICovDQorLyogV2UgbmVlZCB0byB1c2UgcmVsYXRpdmUgYWRkcmVz c2luZywgYW5kIHdpdGggQ1MgdG8gdG9wIGl0IGFsbCwgc2luY2Ugd2UNCisgICBtdXN0IG1ha2Ug YXMgZmV3IGNoYW5nZXMgdG8gdGhlIHJlZ2lzdGVycyBhcyBwb3NzaWJsZS4gIElQLXJlbGF0aXZl DQorICAgYWRkcmVzc2luZyBsaWtlIG9uIGFtZDY0IHdvdWxkIG1ha2UgbGlmZSB3YXkgZWFzaWVy IGhlcmUuICovDQorLmNvZGUxNg0KK0ZVTkNUSU9OKGdydWJfZHJpdmVtYXBfaW50MTNfaGFuZGxl cikNCisgIHB1c2ggJWJwDQorICBtb3YgJXNwLCAlYnANCisgIHB1c2ggJWF4ICAvKiBXZSdsbCBu ZWVkIGl0IGxhdGVyIHRvIGRldGVybWluZSB0aGUgdXNlZCBCSU9TIGZ1bmN0aW9uICovDQorDQor ICAvKiBNYXAgdGhlIGRyaXZlIG51bWJlciAoYWx3YXlzIGluIERMPykgKi8NCisgIHB1c2ggJWF4 DQorICBwdXNoICVieA0KKyAgcHVzaCAlc2kNCisgIG1vdiAkR1JVQl9EUklWRU1BUF9JTlQxM0hf T0ZGU0VUKGdydWJfZHJpdmVtYXBfaW50MTNfbWFwc3RhcnQpLCAlYngNCisgIHhvciAlc2ksICVz aQ0KKzE6bW92dyAlY3M6KCVieCwlc2kpLCAlYXgNCisgIGNtcCAlYWgsICVhbA0KKyAganogM2Yg LyogRFJWPURTVCA9PiBtYXAgZW5kIC0gZHJpdmUgbm90IHJlbWFwcGVkLCBsZWF2ZSBETCBhcy1p cyAqLw0KKyAgY21wICVkbCwgJWFsDQorICBqeiAyZiAvKiBGb3VuZCAtIGRyaXZlIHJlbWFwcGVk LCBtb2RpZnkgREwgKi8NCisgIGFkZCAkMiwgJXNpDQorICBqbXAgMWIgLyogTm90IGZvdW5kLCBi dXQgbW9yZSByZW1haW5pbmcsIGxvb3AgICovDQorMjptb3YgJWFoLCAlZGwNCiszOnBvcCAlc2kN CisgIHBvcCAlYngNCisgIHhjaGd3ICVheCwgLTQoJWJwKSAvKiBSZWNvdmVyIHRoZSBvbGQgQVgg YW5kIHNhdmUgdGhlIG1hcCBlbnRyeSBmb3IgbGF0ZXIgKi8NCisgIA0KKyAgcHVzaCAlYnANCisg IC8qIFNpbXVsYXRlIGludGVycnVwdCBjYWxsOiBwdXNoIGZsYWdzIGFuZCBkbyBhIGZhciBjYWxs IGluIG9yZGVyIHRvIHNldA0KKyAgICAgdGhlIHN0YWNrIHRoZSB3YXkgdGhlIG9sZCBoYW5kbGVy IGV4cGVjdHMgaXQgc28gdGhhdCBpdHMgaXJldCB3b3JrcyAqLw0KKyAgcHVzaCA2KCVicCkNCisg IG1vdncgKCVicCksICVicCAgLyogUmVzdG9yZSB0aGUgY2FsbGVyIEJQIChpcyB0aGlzIG5lZWRl ZCBhbmQvb3Igc2Vuc2libGU/KSAqLw0KKyAgbGNhbGwgKiVjczpHUlVCX0RSSVZFTUFQX0lOVDEz SF9PRkZTRVQoZ3J1Yl9kcml2ZW1hcF9pbnQxM19vbGRoYW5kbGVyKQ0KKyAgcG9wICVicCAvKiBU aGUgcHVzaGVkIGZsYWdzIHdlcmUgcmVtb3ZlZCBieSBpcmV0ICovDQorICAvKiBTZXQgdGhlIHNh dmVkIGZsYWdzIHRvIHdoYXQgdGhlIGludDEzaCBoYW5kbGVyIHJldHVybmVkICovDQorICBwdXNo ICVheA0KKyAgcHVzaGYNCisgIHBvcCAlYXgNCisgIG1vdncgJWF4LCA2KCVicCkNCisgIHBvcCAl YXgNCisNCisgIC8qIFJldmVyc2UgbWFwIGFueSByZXR1cm5lZCBkcml2ZSBudW1iZXIgaWYgdGhl IGRhdGEgcmV0dXJuZWQgaW5jbHVkZXMgaXQuICANCisgICAgIFRoZSBvbmx5IGZ1bmMgdGhhdCBk b2VzIHRoaXMgc2VlbXMgdG8gYmUgb3JpZ0FIID0gMHgwOCwgYnV0IG1hbnkgQklPUw0KKyAgICAg cmVmcyBzYXkgcmV0REwgPSAjIG9mIGRyaXZlcyBjb25uZWN0ZWQuICBIb3dldmVyLCB0aGUgR1JV QiBMZWdhY3kgY29kZQ0KKyAgICAgdHJlYXRzIHRoaXMgYXMgdGhlIF9kcml2ZSBudW1iZXJfIGFu ZCAidW5kb2VzIiB0aGUgcmVtYXBwaW5nLiAgVGh1cywNCisgICAgIHRoaXMgc2VjdGlvbiBoYXMg YmVlbiBkaXNhYmxlZCBmb3IgdGVzdGluZyBpZiBpdCdzIHJlcXVpcmVkICovDQorIyAgY21wYiAk MHgwOCwgLTEoJWJwKSAvKiBDYWxsZXIncyBBSCAqLw0KKyMgIGpuZSA0Zg0KKyMgIHhjaGd3ICVh eCwgLTQoJWJwKSAvKiBNYXAgZW50cnkgdXNlZCAqLw0KKyMgIGNtcCAlYWgsICVhbCAgLyogRFJW PURTVCA9PiBkcml2ZSBub3QgcmVtYXBwZWQgKi8NCisjICBqZSA0Zg0KKyMgIG1vdiAlYWgsICVk bCAgLyogVW5kbyByZW1hcCAqLw0KKw0KKzQ6bW92ICVicCwgJXNwDQorICBwb3AgJWJwDQorICBp cmV0DQorLyogVGhpcyBsYWJlbCBNVVNUIGJlIGF0IHRoZSBlbmQgb2YgdGhlIGNvcGllZCBibG9j aywgc2luY2UgdGhlIGluc3RhbGxlciBjb2RlDQorICAgcmVzZXJ2ZXMgYWRkaXRpb25hbCBzcGFj ZSBmb3IgbWFwcGluZ3MgYXQgcnVudGltZSBhbmQgY29waWVzIHRoZW0gb3ZlciBpdCAqLw0KKy5h bGlnbiAyDQorVkFSSUFCTEUoZ3J1Yl9kcml2ZW1hcF9pbnQxM19tYXBzdGFydCkNCisvKiBDb3B5 IHN0b3BzIGhlcmUgKi8NCisuY29kZTMyDQorVkFSSUFCTEUoZ3J1Yl9kcml2ZW1hcF9pbnQxM19z aXplKQ0KKyAgLndvcmQgR1JVQl9EUklWRU1BUF9JTlQxM0hfT0ZGU0VUKGdydWJfZHJpdmVtYXBf aW50MTNfc2l6ZSkNCisNCkluZGV4OiBjb25mL2kzODYtcGMucm1rDQo9PT09PT09PT09PT09PT09 PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09DQotLS0g Y29uZi9pMzg2LXBjLnJtawkocmV2aXNpw7NuOiAxNzcxKQ0KKysrIGNvbmYvaTM4Ni1wYy5ybWsJ KGNvcGlhIGRlIHRyYWJham8pDQpAQCAtMTU4LDcgKzE1OCw3IEBADQogCXZiZS5tb2QgdmJldGVz dC5tb2QgdmJlaW5mby5tb2QgdmlkZW8ubW9kIGdmeHRlcm0ubW9kIFwNCiAJdmlkZW90ZXN0Lm1v ZCBwbGF5Lm1vZCBiaXRtYXAubW9kIHRnYS5tb2QgY3B1aWQubW9kIHNlcmlhbC5tb2QJXA0KIAlh dGEubW9kIHZnYS5tb2QgbWVtZGlzay5tb2QganBlZy5tb2QgcG5nLm1vZCBwY2kubW9kIGxzcGNp Lm1vZCBcDQotCWFvdXQubW9kIF9ic2QubW9kIGJzZC5tb2QNCisJYW91dC5tb2QgX2JzZC5tb2Qg YnNkLm1vZCBkcml2ZW1hcC5tb2QNCiANCiAjIEZvciBiaW9zZGlzay5tb2QuDQogYmlvc2Rpc2tf bW9kX1NPVVJDRVMgPSBkaXNrL2kzODYvcGMvYmlvc2Rpc2suYw0KQEAgLTMyNSw0ICszMjUsMTEg QEANCiBic2RfbW9kX0NGTEFHUyA9ICQoQ09NTU9OX0NGTEFHUykNCiBic2RfbW9kX0xERkxBR1Mg PSAkKENPTU1PTl9MREZMQUdTKQ0KIA0KKyMgRm9yIGRyaXZlbWFwLm1vZC4NCitkcml2ZW1hcF9t b2RfU09VUkNFUyA9IGNvbW1hbmRzL2kzODYvcGMvZHJpdmVtYXAuYyBcDQorICAgICAgICAgICAg ICAgICAgICAgICBjb21tYW5kcy9pMzg2L3BjL2RyaXZlbWFwX2ludDEzaC5TDQorZHJpdmVtYXBf bW9kX0FTRkxBR1MgPSAkKENPTU1PTl9BU0ZMQUdTKQ0KK2RyaXZlbWFwX21vZF9DRkxBR1MgPSAk KENPTU1PTl9DRkxBR1MpDQorZHJpdmVtYXBfbW9kX0xERkxBR1MgPSAkKENPTU1PTl9MREZMQUdT KQ0KKw0KIGluY2x1ZGUgJChzcmNkaXIpL2NvbmYvY29tbW9uLm1rDQpJbmRleDogaW5jbHVkZS9n cnViL2xvYWRlci5oDQo9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09 PT09PT09PT09PT09PT09PT09PT09PT09DQotLS0gaW5jbHVkZS9ncnViL2xvYWRlci5oCShyZXZp c2nDs246IDE3NzEpDQorKysgaW5jbHVkZS9ncnViL2xvYWRlci5oCShjb3BpYSBkZSB0cmFiYWpv KQ0KQEAgLTM3LDcgKzM3LDIzIEBADQogLyogVW5zZXQgY3VycmVudCBsb2FkZXIsIGlmIGFueS4g ICovDQogdm9pZCBFWFBPUlRfRlVOQyhncnViX2xvYWRlcl91bnNldCkgKHZvaWQpOw0KIA0KLS8q IENhbGwgdGhlIGJvb3QgaG9vayBpbiBjdXJyZW50IGxvYWRlci4gVGhpcyBtYXkgb3IgbWF5IG5v dCByZXR1cm4sDQordHlwZWRlZiBzdHJ1Y3QgaG9va2xpc3Rfbm9kZSAqZ3J1Yl9wcmVib290X2hv b2tpZDsNCisNCisvKiBSZWdpc3RlciBhIGZ1bmN0aW9uIHRvIGJlIGNhbGxlZCBiZWZvcmUgdGhl IGxvYWRlciAiYm9vdCIgZnVuY3Rpb24uICBSZXR1cm5zDQorICAgYW4gaWQgdGhhdCBjYW4gYmUg bGF0ZXIgdXNlZCB0byB1bnJlZ2lzdGVyIHRoZSBwcmVib290IChpLmUuIG9uIG1vZHVsZQ0KKyAg IHVubG9hZCkuICBJZiBBQk9SVF9PTl9FUlJPUiBpcyBzZXQsIHRoZSBib290IHNlcXVlbmNlIHdp bGwgYWJvcnQgaWYgYW55IG9mDQorICAgdGhlIHJlZ2lzdGVyZWQgZnVuY3Rpb25zIHJldHVybiBh bnl0aGluZyBlbHNlIHRoYW4gR1JVQl9FUlJfTk9ORS4NCisgICBPbiBlcnJvciwgdGhlIHJldHVy biB2YWx1ZSB3aWxsIGNvbXBhcmUgZXF1YWwgdG8gMCBhbmQgdGhlIGVycm9yIGluZm9ybWF0aW9u DQorICAgd2lsbCBiZSBhdmFpbGFibGUgaW4gZ3J1Yl9lcnJuby4gIEhvd2V2ZXIsIGlmIHRoZSBj YWxsIGlzIHN1Y2Nlc3NmdWwgdGhhdA0KKyAgIHZhcmlhYmxlIGlzIF9ub3RfIG1vZGlmaWVkLiAq Lw0KK2dydWJfcHJlYm9vdF9ob29raWQgRVhQT1JUX0ZVTkMoZ3J1Yl9sb2FkZXJfcmVnaXN0ZXJf cHJlYm9vdCkNCisgICAgICAgICAgIChncnViX2Vycl90ICgqaG9vaykgKHZvaWQpLCBpbnQgYWJv cnRfb25fZXJyb3IpOw0KKw0KKy8qIFVucmVnaXN0ZXIgYSBwcmVib290IGhvb2sgYnkgdGhlIGlk IHJldHVybmVkIGJ5IGxvYWRlcl9yZWdpc3Rlcl9wcmVib290LiAgDQorICAgVGhpcyBmdW5jdGlv bnMgYmVjb21lcyBhIG5vLW9wIGlmIG5vIHN1Y2ggZnVuY3Rpb24gaXMgcmVnaXN0ZXJlZCAqLw0K K3ZvaWQgRVhQT1JUX0ZVTkMoZ3J1Yl9sb2FkZXJfdW5yZWdpc3Rlcl9wcmVib290KSAoZ3J1Yl9w cmVib290X2hvb2tpZCBpZCk7DQorDQorLyogQ2FsbCB0aGUgYm9vdCBob29rIGluIGN1cnJlbnQg bG9hZGVyLiAgVGhpcyBtYXkgb3IgbWF5IG5vdCByZXR1cm4sDQogICAgZGVwZW5kaW5nIG9uIHRo ZSBzZXR0aW5nIGJ5IGdydWJfbG9hZGVyX3NldC4gICovDQogZ3J1Yl9lcnJfdCBFWFBPUlRfRlVO QyhncnViX2xvYWRlcl9ib290KSAodm9pZCk7DQogDQpJbmRleDoga2Vybi9sb2FkZXIuYw0KPT09 PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09 PT09PT09PQ0KLS0tIGtlcm4vbG9hZGVyLmMJKHJldmlzacOzbjogMTc3MSkNCisrKyBrZXJuL2xv YWRlci5jCShjb3BpYSBkZSB0cmFiYWpvKQ0KQEAgLTYxLDExICs2MSw4NSBAQA0KICAgZ3J1Yl9s b2FkZXJfbG9hZGVkID0gMDsNCiB9DQogDQorc3RydWN0IGhvb2tsaXN0X25vZGUNCit7DQorICBn cnViX2Vycl90ICgqaG9vaykgKHZvaWQpOw0KKyAgaW50IGFib3J0X29uX2Vycm9yOw0KKyAgc3Ry dWN0IGhvb2tsaXN0X25vZGUgKm5leHQ7DQorfTsNCisNCitzdGF0aWMgc3RydWN0IGhvb2tsaXN0 X25vZGUgKnByZWJvb3RfaG9va3MgPSAwOw0KKw0KK2dydWJfcHJlYm9vdF9ob29raWQNCitncnVi X2xvYWRlcl9yZWdpc3Rlcl9wcmVib290IChncnViX2Vycl90ICgqaG9vaykgKHZvaWQpLCBpbnQg YWJvcnRfb25fZXJyb3IpDQorew0KKyAgZ3J1Yl9wcmVib290X2hvb2tpZCBuZXdlbnRyeTsNCisg IGlmICghaG9vaykNCisgICAgew0KKyAgICAgIGdydWJfZXJyb3IgKEdSVUJfRVJSX0JBRF9BUkdV TUVOVCwgInByZWJvb3QgaG9vayBtdXN0IG5vdCBiZSBOVUxMIik7DQorICAgICAgcmV0dXJuIDA7 DQorICAgIH0NCisgIG5ld2VudHJ5ID0gZ3J1Yl9tYWxsb2MgKHNpemVvZiAoc3RydWN0IGhvb2ts aXN0X25vZGUpKTsNCisgIGlmICghbmV3ZW50cnkpDQorICAgIHsNCisgICAgICBncnViX2Vycm9y IChHUlVCX0VSUl9PVVRfT0ZfTUVNT1JZLCAiY2Fubm90IGFsbG9jIGEgaG9va2luZm8gc3RydWN0 dXJlIik7DQorICAgICAgcmV0dXJuIDA7DQorICAgIH0NCisgIGVsc2UNCisgICAgew0KKyAgICAg IG5ld2VudHJ5LT5ob29rID0gaG9vazsNCisgICAgICBuZXdlbnRyeS0+YWJvcnRfb25fZXJyb3Ig PSBhYm9ydF9vbl9lcnJvcjsNCisgICAgICBuZXdlbnRyeS0+bmV4dCA9IHByZWJvb3RfaG9va3M7 DQorICAgICAgcHJlYm9vdF9ob29rcyA9IG5ld2VudHJ5Ow0KKyAgICAgIHJldHVybiBuZXdlbnRy eTsNCisgICAgfQ0KK30NCisNCit2b2lkDQorZ3J1Yl9sb2FkZXJfdW5yZWdpc3Rlcl9wcmVib290 IChncnViX3ByZWJvb3RfaG9va2lkIGlkKQ0KK3sNCisgIGdydWJfcHJlYm9vdF9ob29raWQgZW50 cnkgPSAwOw0KKyAgZ3J1Yl9wcmVib290X2hvb2tpZCBzZWFyY2ggPSBwcmVib290X2hvb2tzOw0K KyAgZ3J1Yl9wcmVib290X2hvb2tpZCBwcmV2aW91cyA9IDA7DQorDQorICBpZiAoMCA9PSBpZCkN CisgICAgcmV0dXJuOw0KKw0KKyAgd2hpbGUgKHNlYXJjaCkNCisgICAgew0KKyAgICAgIGlmIChz ZWFyY2ggPT0gaWQpDQorICAgICAgICB7DQorICAgICAgICAgIGVudHJ5ID0gc2VhcmNoOw0KKyAg ICAgICAgICBicmVhazsNCisgICAgICAgIH0NCisgICAgICBwcmV2aW91cyA9IHNlYXJjaDsNCisg ICAgICBzZWFyY2ggPSBzZWFyY2gtPm5leHQ7DQorICAgIH0NCisNCisgIGlmIChlbnRyeSkNCisg ICAgew0KKyAgICAgIGlmIChwcmV2aW91cykNCisgICAgICAgIHByZXZpb3VzLT5uZXh0ID0gZW50 cnktPm5leHQ7DQorICAgICAgZWxzZSBwcmVib290X2hvb2tzID0gZW50cnktPm5leHQ7IC8qIEVu dHJ5IHdhcyBoZWFkIG9mIGxpc3QgKi8NCisgICAgICBncnViX2ZyZWUgKGVudHJ5KTsNCisgICAg fQ0KK30NCisNCiBncnViX2Vycl90DQogZ3J1Yl9sb2FkZXJfYm9vdCAodm9pZCkNCiB7DQorICBn cnViX3ByZWJvb3RfaG9va2lkIGVudHJ5ID0gcHJlYm9vdF9ob29rczsNCisNCiAgIGlmICghIGdy dWJfbG9hZGVyX2xvYWRlZCkNCiAgICAgcmV0dXJuIGdydWJfZXJyb3IgKEdSVUJfRVJSX05PX0tF Uk5FTCwgIm5vIGxvYWRlZCBrZXJuZWwiKTsNCisgIA0KKyAgd2hpbGUgKGVudHJ5KQ0KKyAgICB7 DQorICAgICAgZ3J1Yl9lcnJfdCBwb3NzaWJsZV9lcnJvciA9IGVudHJ5LT5ob29rKCk7DQorICAg ICAgaWYgKHBvc3NpYmxlX2Vycm9yICE9IEdSVUJfRVJSX05PTkUgJiYgZW50cnktPmFib3J0X29u X2Vycm9yKQ0KKyAgICAgICAgcmV0dXJuIHBvc3NpYmxlX2Vycm9yOw0KKyAgICAgIGVudHJ5ID0g ZW50cnktPm5leHQ7DQorICAgIH0NCiANCiAgIGlmIChncnViX2xvYWRlcl9ub3JldHVybikNCiAg ICAgZ3J1Yl9tYWNoaW5lX2ZpbmkgKCk7DQo= --=-sKBwnpaU3EMF11q+6YxZ-- --=-7G2BXokK2O8wQUsdcvNa Content-Type: application/pgp-signature; name=signature.asc Content-Description: Esta parte del mensaje =?ISO-8859-1?Q?est=E1?= firmada digitalmente -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.6 (GNU/Linux) iQIVAwUASJeMYaSl+Fbdeo72AQLgAA/+ODsWIqFMO9j0rh9eBuyHU/WUeu6e+FGR aXNUlOfGVU6EOj3KxcMWolpQXDOdeZ0CvcYC7Nv6uGpek4qLwCf8Ms2XklSZd6vf +AhjtqnrxK+YFH9vCKy5ayVauPbsceqvY0JtQ6LBEpfGiNYiVQrnul6xUl+vbeR3 4ZbLYnFyHgfuGLaHcTpqKWDjeWyty0FmEs7bKZ7xIDQaFAZhU8TE5UrDEUBLxEED eAoPDoTDBu3fMO2ocoQXkFzTqeNy2viqzdvszKlP0rJM41W5F5jpnQRLvwNS9JCI aoT1m1hzF6Etgqb7q38B5LXJHoKEHBUy/khqYQXptpn2YmS30OlI5MWqZe5nNn7w iDURNySy2E0NFYjwBQHF10/Wv0Bgm6cgdAbIDIE3hyYodiNbUuYUqkiRlGTM9kk4 cI41cKkJgQgP0StsS5jOaqirxvNgWNNrqrnxGbeK9w+9gqvy9urS4Cd+ICN7aewr hKxuHBktWFIAUzd6185IwDvCZEPj/Ue52/vDWaaMXJbKPggQy68NgFXGkKH27Mnr x4ug7sVIFn+ZF4pexPhF2b53EzYBwKPGHJ9Qh5JFqnEgPgwnBEMCqaQ3BGCjvMw2 wjG4/BX6E1AEFZp6AU/BxBBQWaXyyvkhjBEK4AfezsmF/ZRo8VqSH+l17ITvDg7T 9HjOnqEO57M= =pHnt -----END PGP SIGNATURE----- --=-7G2BXokK2O8wQUsdcvNa--