From cd2d431cef36e2c86c5228071000ef8f52f55e97d84fe14efb8c7d8e5bb71463 Mon Sep 17 00:00:00 2001 From: Mike Latimer Date: Wed, 23 Aug 2017 04:19:19 +0000 Subject: [PATCH] Accepting request 518315 from home:mlatimer:branches:Virtualization:VMware Update to 10.1.10 OBS-URL: https://build.opensuse.org/request/show/518315 OBS-URL: https://build.opensuse.org/package/show/Virtualization:VMware/open-vm-tools?expand=0&rev=348 --- glibc-sysmacros.patch | 12 - open-vm-tools-10.1.10-6082533.tar.gz | 3 + open-vm-tools-10.1.5-5055683.tar.gz | 3 - open-vm-tools.changes | 32 + open-vm-tools.spec | 12 +- resolutionKMS-wayland.patch | 2283 ++++++++++++++++++++++++++ 6 files changed, 2325 insertions(+), 20 deletions(-) delete mode 100644 glibc-sysmacros.patch create mode 100644 open-vm-tools-10.1.10-6082533.tar.gz delete mode 100644 open-vm-tools-10.1.5-5055683.tar.gz create mode 100644 resolutionKMS-wayland.patch diff --git a/glibc-sysmacros.patch b/glibc-sysmacros.patch deleted file mode 100644 index 26c8d88..0000000 --- a/glibc-sysmacros.patch +++ /dev/null @@ -1,12 +0,0 @@ ---- a/open-vm-tools/lib/wiper/wiperPosix.c 2017-02-11 03:06:43.000000000 -0700 -+++ b/open-vm-tools/lib/wiper/wiperPosix.c 2017-03-27 15:06:41.269310652 -0600 -@@ -31,6 +31,9 @@ - #include - #if defined(__linux__) || defined(sun) - # include -+# if defined(__linux__) -+# include -+# endif - #elif defined(__FreeBSD__) || defined(__APPLE__) - # include - # include diff --git a/open-vm-tools-10.1.10-6082533.tar.gz b/open-vm-tools-10.1.10-6082533.tar.gz new file mode 100644 index 0000000..6860d3f --- /dev/null +++ b/open-vm-tools-10.1.10-6082533.tar.gz @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4632d815996e7f2c283818b0d84b0c4cf2fb82a0897d77aee0f8cbcdc5678c61 +size 5111726 diff --git a/open-vm-tools-10.1.5-5055683.tar.gz b/open-vm-tools-10.1.5-5055683.tar.gz deleted file mode 100644 index 9dfa132..0000000 --- a/open-vm-tools-10.1.5-5055683.tar.gz +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:5057513cdbde821c4abc6dcd7e8633febf4080721937526af61c8f1872575276 -size 5133905 diff --git a/open-vm-tools.changes b/open-vm-tools.changes index fa36c4a..171c175 100644 --- a/open-vm-tools.changes +++ b/open-vm-tools.changes @@ -1,3 +1,35 @@ +------------------------------------------------------------------- +Mon Aug 21 16:01:33 UTC 2017 - mlatimer@suse.com + +- open-vm-tools fails to correctly set screen resolution under + Wayland environments (boo#1054800) + + resolutionKMS-wayland.patch + +------------------------------------------------------------------- +Tue Aug 15 19:02:33 UTC 2017 - mlatimer@suse.com + +- Update to 10.1.10 stable release (boo#1051977, bsc#1052129) + + Map certain PAM errors to VGAUTH_E_AUTHENTICATION_DENIED. + + Exclude non-directory and non-existing paths during quiescing. + + Fix timesync state to be uncalibrated when adjustment is large + (>60ms). + + Fix an invalid class pointer access when the VSS provider is + not installed. + + Add support for the new selection target name "text/rtf" for + copy/paste. + + VMCI: reset datagram buffer pointer on dealloc + + randomly generate tmp directory name + + Previously Common Agent Framework (CAF) builds were linking against + specific versions of PCRE and libiconv. That restriction has been + removed. + + Reverts commit 7023998ba5594871a658c5ef1be4dbda6c0158eb to prevent + intermittent hangs during soft reboots of RHEL 6.8 Linux VM. + + Includes fix for VMs freezing during snapshots (bsc#1051627) + (Thaw filesystems if the snapshot commit message to VMX fails. + Commit b443e6456ffda66c0279032ab932ef271f8e1ae6) +- Drop unnecessary patch: + + glibc-sysmacros.patch + ------------------------------------------------------------------- Fri Mar 31 20:55:06 UTC 2017 - ken@suse.com diff --git a/open-vm-tools.spec b/open-vm-tools.spec index e1cb613..bc4bb74 100644 --- a/open-vm-tools.spec +++ b/open-vm-tools.spec @@ -73,8 +73,8 @@ Name: open-vm-tools %define subname open-vm-tools %define tarname open-vm-tools -%define bldnum 5055683 -Version: 10.1.5 +%define bldnum 6082533 +Version: 10.1.10 Release: 0 Summary: Open Virtual Machine Tools License: BSD-3-Clause and GPL-2.0 and LGPL-2.1 @@ -143,7 +143,7 @@ Requires(pre): %insserv_prereq %endif ExclusiveArch: %ix86 x86_64 Patch0: Report-SLES12-SAP-guest-OS-as-SLES12.patch -Patch1: glibc-sysmacros.patch +Patch1: resolutionKMS-wayland.patch %if %{with systemd} %systemd_requires @@ -208,11 +208,11 @@ Those are the development headers for libvmtools. They are needed if you intend to create own plugins for vmtoolsd. %prep -%setup -q -n %{tarname}-%{version}-%{bldnum}/%{subname} +%setup -q -n %{tarname}-%{version}-%{bldnum} # fix for an rpmlint warning regarding wrong line feeds sed -i -e "s/\r//" README %patch0 -p2 -%patch1 -p2 +%patch1 -p1 %build # disable warning unused-but-set-variable which will raise error because of -Werror @@ -259,6 +259,7 @@ chmod 755 configure --without-xerces \ %endif --with-udev-rules-dir=%{_udevrulesdir} \ + --enable-resolutionkms \ --disable-static make @@ -442,6 +443,7 @@ rm -rf %{buildroot} %{_libdir}/%{name}/plugins/vmsvc/libpowerOps.so %{_libdir}/%{name}/plugins/vmsvc/libtimeSync.so %{_libdir}/%{name}/plugins/vmsvc/libvmbackup.so +%{_libdir}/%{name}/plugins/vmsvc/libresolutionKMS.so %{_libdir}/%{name}/plugins/common/libhgfsServer.so %{_libdir}/%{name}/plugins/common/libvix.so %{_bindir}/vmhgfs-fuse diff --git a/resolutionKMS-wayland.patch b/resolutionKMS-wayland.patch new file mode 100644 index 0000000..96db90e --- /dev/null +++ b/resolutionKMS-wayland.patch @@ -0,0 +1,2283 @@ +diff --git a/configure.ac b/configure.ac +index 20370ae..9e4272e 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -235,6 +235,14 @@ AC_ARG_ENABLE( + [enable_tests="$enableval"], + [enable_tests="auto"]) + ++AC_ARG_ENABLE( ++ resolutionkms, ++ AS_HELP_STRING( ++ [--enable-resolutionkms], ++ [build the linux / unix resolutionkms module.]), ++ [], ++ [enable_resolutionkms="auto"]) ++ + AM_INIT_AUTOMAKE + + ### +@@ -792,6 +800,7 @@ AC_CHECK_FUNCS( + [VIX_LIBADD="$VIX_LIBADD -ldl" + LIBVMTOOLS_LIBADD="$LIBVMTOOLS_LIBADD -ldl" + VGAUTH_LIBADD="$VGAUTH_LIBADD -ldl" ++ RESOLUTIONSET_LIBADD="$RESOLUTIONSET_LIBADD -ldl" + ], + [AC_MSG_ERROR( + [dlopen was not found, but is required for open-vm-tools to function properly. Please contact your OS vendor.])])]) +@@ -1265,6 +1274,15 @@ if test "$os" = "linux"; then + MODULES="$MODULES vmblock vmsync" + fi + buildHgfsmounter=yes ++ if test "x$enable_resolutionkms" != "xno"; then ++ PKG_CHECK_MODULES( ++ [LIBUDEV], ++ libdrm libudev, ++ [LIBUDEV_CFLAGS="$LIBUDEV_CFLAGS -DHAVE_LIBUDEV"], ++ [AC_MSG_WARN( ++ [Missing libdrm or libudev. The resolutionKMS plugin will search for them at run-time.])]) ++ enable_resolutionkms="yes" ++ fi + fi + + if test "$os" = "freebsd" || test "$os" = "kfreebsd-gnu"; then +@@ -1352,6 +1370,14 @@ else + UDEVRULESDIR="" + fi + ++if test "x$enable_resolutionkms" = "xauto"; then ++ enable_resolutionkms="no" ++fi ++ ++if test "x$enable_resolutionkms" = "xyes"; then ++ CPPFLAGS="$CPPFLAGS -DENABLE_RESOLUTIONKMS" ++fi ++ + AM_CONDITIONAL(BUILD_HGFSMOUNTER, test "$buildHgfsmounter" = "yes") + AM_CONDITIONAL(LINUX, test "$os" = "linux") + AM_CONDITIONAL(SOLARIS, test "$os" = "solaris") +@@ -1382,6 +1408,7 @@ AM_CONDITIONAL(ENABLE_CAF, test "$enable_caf" = "yes") + AM_CONDITIONAL(HAVE_VSOCK, test "$os" = "linux") + AM_CONDITIONAL(HAVE_MKDTEMP, test "$have_mkdtemp" = "yes") + AM_CONDITIONAL(HAVE_UDEV, test "$have_udev" = "yes") ++AM_CONDITIONAL(ENABLE_RESOLUTIONKMS, test "x$enable_resolutionkms" = "xyes") + + if test "$have_xsm" != "yes"; then + AC_DEFINE([NO_XSM], 1, []) +@@ -1492,6 +1519,7 @@ AC_SUBST([LIB_AUTH_CPPFLAGS]) + AC_SUBST([LIB_IMPERSONATE_CPPFLAGS]) + AC_SUBST([LIB_USER_CPPFLAGS]) + AC_SUBST([LIBVMTOOLS_LIBADD]) ++AC_SUBST([RESOLUTIONSET_LIBADD]) + + ### Program substs + +@@ -1564,6 +1592,7 @@ AC_CONFIG_FILES([ \ + services/plugins/hgfsServer/Makefile \ + services/plugins/powerOps/Makefile \ + services/plugins/resolutionSet/Makefile \ ++ services/plugins/resolutionKMS/Makefile \ + services/plugins/timeSync/Makefile \ + services/plugins/vix/Makefile \ + services/plugins/vmbackup/Makefile \ +diff --git a/services/plugins/Makefile.am b/services/plugins/Makefile.am +index 5d75718..5deb281 100644 +--- a/services/plugins/Makefile.am ++++ b/services/plugins/Makefile.am +@@ -34,6 +34,14 @@ endif + if HAVE_X11 + SUBDIRS += resolutionSet + endif ++if ENABLE_RESOLUTIONKMS ++if !HAVE_X11 ++# resolutionKMS needs resolutionCommon, which lives in ++# the resolutionSet sub directory ++ SUBDIRS += resolutionSet ++endif ++SUBDIRS += resolutionKMS ++endif + SUBDIRS += timeSync + SUBDIRS += vix + SUBDIRS += vmbackup +diff --git a/services/plugins/resolutionKMS/COPYING b/services/plugins/resolutionKMS/COPYING +new file mode 100644 +index 0000000..9c6a6cc +--- /dev/null ++++ b/services/plugins/resolutionKMS/COPYING +@@ -0,0 +1,502 @@ ++ GNU LESSER GENERAL PUBLIC LICENSE ++ Version 2.1, February 1999 ++ ++ Copyright (C) 1991, 1999 Free Software Foundation, Inc. ++ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ++ Everyone is permitted to copy and distribute verbatim copies ++ of this license document, but changing it is not allowed. ++ ++[This is the first released version of the Lesser GPL. It also counts ++ as the successor of the GNU Library Public License, version 2, hence ++ the version number 2.1.] ++ ++ Preamble ++ ++ The licenses for most software are designed to take away your ++freedom to share and change it. By contrast, the GNU General Public ++Licenses are intended to guarantee your freedom to share and change ++free software--to make sure the software is free for all its users. ++ ++ This license, the Lesser General Public License, applies to some ++specially designated software packages--typically libraries--of the ++Free Software Foundation and other authors who decide to use it. You ++can use it too, but we suggest you first think carefully about whether ++this license or the ordinary General Public License is the better ++strategy to use in any particular case, based on the explanations below. ++ ++ When we speak of free software, we are referring to freedom of use, ++not price. Our General Public Licenses are designed to make sure that ++you have the freedom to distribute copies of free software (and charge ++for this service if you wish); that you receive source code or can get ++it if you want it; that you can change the software and use pieces of ++it in new free programs; and that you are informed that you can do ++these things. ++ ++ To protect your rights, we need to make restrictions that forbid ++distributors to deny you these rights or to ask you to surrender these ++rights. These restrictions translate to certain responsibilities for ++you if you distribute copies of the library or if you modify it. ++ ++ For example, if you distribute copies of the library, whether gratis ++or for a fee, you must give the recipients all the rights that we gave ++you. You must make sure that they, too, receive or can get the source ++code. If you link other code with the library, you must provide ++complete object files to the recipients, so that they can relink them ++with the library after making changes to the library and recompiling ++it. And you must show them these terms so they know their rights. ++ ++ We protect your rights with a two-step method: (1) we copyright the ++library, and (2) we offer you this license, which gives you legal ++permission to copy, distribute and/or modify the library. ++ ++ To protect each distributor, we want to make it very clear that ++there is no warranty for the free library. Also, if the library is ++modified by someone else and passed on, the recipients should know ++that what they have is not the original version, so that the original ++author's reputation will not be affected by problems that might be ++introduced by others. ++ ++ Finally, software patents pose a constant threat to the existence of ++any free program. We wish to make sure that a company cannot ++effectively restrict the users of a free program by obtaining a ++restrictive license from a patent holder. Therefore, we insist that ++any patent license obtained for a version of the library must be ++consistent with the full freedom of use specified in this license. ++ ++ Most GNU software, including some libraries, is covered by the ++ordinary GNU General Public License. This license, the GNU Lesser ++General Public License, applies to certain designated libraries, and ++is quite different from the ordinary General Public License. We use ++this license for certain libraries in order to permit linking those ++libraries into non-free programs. ++ ++ When a program is linked with a library, whether statically or using ++a shared library, the combination of the two is legally speaking a ++combined work, a derivative of the original library. The ordinary ++General Public License therefore permits such linking only if the ++entire combination fits its criteria of freedom. The Lesser General ++Public License permits more lax criteria for linking other code with ++the library. ++ ++ We call this license the "Lesser" General Public License because it ++does Less to protect the user's freedom than the ordinary General ++Public License. It also provides other free software developers Less ++of an advantage over competing non-free programs. These disadvantages ++are the reason we use the ordinary General Public License for many ++libraries. However, the Lesser license provides advantages in certain ++special circumstances. ++ ++ For example, on rare occasions, there may be a special need to ++encourage the widest possible use of a certain library, so that it becomes ++a de-facto standard. To achieve this, non-free programs must be ++allowed to use the library. A more frequent case is that a free ++library does the same job as widely used non-free libraries. In this ++case, there is little to gain by limiting the free library to free ++software only, so we use the Lesser General Public License. ++ ++ In other cases, permission to use a particular library in non-free ++programs enables a greater number of people to use a large body of ++free software. For example, permission to use the GNU C Library in ++non-free programs enables many more people to use the whole GNU ++operating system, as well as its variant, the GNU/Linux operating ++system. ++ ++ Although the Lesser General Public License is Less protective of the ++users' freedom, it does ensure that the user of a program that is ++linked with the Library has the freedom and the wherewithal to run ++that program using a modified version of the Library. ++ ++ The precise terms and conditions for copying, distribution and ++modification follow. Pay close attention to the difference between a ++"work based on the library" and a "work that uses the library". The ++former contains code derived from the library, whereas the latter must ++be combined with the library in order to run. ++ ++ GNU LESSER GENERAL PUBLIC LICENSE ++ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION ++ ++ 0. This License Agreement applies to any software library or other ++program which contains a notice placed by the copyright holder or ++other authorized party saying it may be distributed under the terms of ++this Lesser General Public License (also called "this License"). ++Each licensee is addressed as "you". ++ ++ A "library" means a collection of software functions and/or data ++prepared so as to be conveniently linked with application programs ++(which use some of those functions and data) to form executables. ++ ++ The "Library", below, refers to any such software library or work ++which has been distributed under these terms. A "work based on the ++Library" means either the Library or any derivative work under ++copyright law: that is to say, a work containing the Library or a ++portion of it, either verbatim or with modifications and/or translated ++straightforwardly into another language. (Hereinafter, translation is ++included without limitation in the term "modification".) ++ ++ "Source code" for a work means the preferred form of the work for ++making modifications to it. For a library, complete source code means ++all the source code for all modules it contains, plus any associated ++interface definition files, plus the scripts used to control compilation ++and installation of the library. ++ ++ Activities other than copying, distribution and modification are not ++covered by this License; they are outside its scope. The act of ++running a program using the Library is not restricted, and output from ++such a program is covered only if its contents constitute a work based ++on the Library (independent of the use of the Library in a tool for ++writing it). Whether that is true depends on what the Library does ++and what the program that uses the Library does. ++ ++ 1. You may copy and distribute verbatim copies of the Library's ++complete source code as you receive it, in any medium, provided that ++you conspicuously and appropriately publish on each copy an ++appropriate copyright notice and disclaimer of warranty; keep intact ++all the notices that refer to this License and to the absence of any ++warranty; and distribute a copy of this License along with the ++Library. ++ ++ You may charge a fee for the physical act of transferring a copy, ++and you may at your option offer warranty protection in exchange for a ++fee. ++ ++ 2. You may modify your copy or copies of the Library or any portion ++of it, thus forming a work based on the Library, and copy and ++distribute such modifications or work under the terms of Section 1 ++above, provided that you also meet all of these conditions: ++ ++ a) The modified work must itself be a software library. ++ ++ b) You must cause the files modified to carry prominent notices ++ stating that you changed the files and the date of any change. ++ ++ c) You must cause the whole of the work to be licensed at no ++ charge to all third parties under the terms of this License. ++ ++ d) If a facility in the modified Library refers to a function or a ++ table of data to be supplied by an application program that uses ++ the facility, other than as an argument passed when the facility ++ is invoked, then you must make a good faith effort to ensure that, ++ in the event an application does not supply such function or ++ table, the facility still operates, and performs whatever part of ++ its purpose remains meaningful. ++ ++ (For example, a function in a library to compute square roots has ++ a purpose that is entirely well-defined independent of the ++ application. Therefore, Subsection 2d requires that any ++ application-supplied function or table used by this function must ++ be optional: if the application does not supply it, the square ++ root function must still compute square roots.) ++ ++These requirements apply to the modified work as a whole. If ++identifiable sections of that work are not derived from the Library, ++and can be reasonably considered independent and separate works in ++themselves, then this License, and its terms, do not apply to those ++sections when you distribute them as separate works. But when you ++distribute the same sections as part of a whole which is a work based ++on the Library, the distribution of the whole must be on the terms of ++this License, whose permissions for other licensees extend to the ++entire whole, and thus to each and every part regardless of who wrote ++it. ++ ++Thus, it is not the intent of this section to claim rights or contest ++your rights to work written entirely by you; rather, the intent is to ++exercise the right to control the distribution of derivative or ++collective works based on the Library. ++ ++In addition, mere aggregation of another work not based on the Library ++with the Library (or with a work based on the Library) on a volume of ++a storage or distribution medium does not bring the other work under ++the scope of this License. ++ ++ 3. You may opt to apply the terms of the ordinary GNU General Public ++License instead of this License to a given copy of the Library. To do ++this, you must alter all the notices that refer to this License, so ++that they refer to the ordinary GNU General Public License, version 2, ++instead of to this License. (If a newer version than version 2 of the ++ordinary GNU General Public License has appeared, then you can specify ++that version instead if you wish.) Do not make any other change in ++these notices. ++ ++ Once this change is made in a given copy, it is irreversible for ++that copy, so the ordinary GNU General Public License applies to all ++subsequent copies and derivative works made from that copy. ++ ++ This option is useful when you wish to copy part of the code of ++the Library into a program that is not a library. ++ ++ 4. You may copy and distribute the Library (or a portion or ++derivative of it, under Section 2) in object code or executable form ++under the terms of Sections 1 and 2 above provided that you accompany ++it with the complete corresponding machine-readable source code, which ++must be distributed under the terms of Sections 1 and 2 above on a ++medium customarily used for software interchange. ++ ++ If distribution of object code is made by offering access to copy ++from a designated place, then offering equivalent access to copy the ++source code from the same place satisfies the requirement to ++distribute the source code, even though third parties are not ++compelled to copy the source along with the object code. ++ ++ 5. A program that contains no derivative of any portion of the ++Library, but is designed to work with the Library by being compiled or ++linked with it, is called a "work that uses the Library". Such a ++work, in isolation, is not a derivative work of the Library, and ++therefore falls outside the scope of this License. ++ ++ However, linking a "work that uses the Library" with the Library ++creates an executable that is a derivative of the Library (because it ++contains portions of the Library), rather than a "work that uses the ++library". The executable is therefore covered by this License. ++Section 6 states terms for distribution of such executables. ++ ++ When a "work that uses the Library" uses material from a header file ++that is part of the Library, the object code for the work may be a ++derivative work of the Library even though the source code is not. ++Whether this is true is especially significant if the work can be ++linked without the Library, or if the work is itself a library. The ++threshold for this to be true is not precisely defined by law. ++ ++ If such an object file uses only numerical parameters, data ++structure layouts and accessors, and small macros and small inline ++functions (ten lines or less in length), then the use of the object ++file is unrestricted, regardless of whether it is legally a derivative ++work. (Executables containing this object code plus portions of the ++Library will still fall under Section 6.) ++ ++ Otherwise, if the work is a derivative of the Library, you may ++distribute the object code for the work under the terms of Section 6. ++Any executables containing that work also fall under Section 6, ++whether or not they are linked directly with the Library itself. ++ ++ 6. As an exception to the Sections above, you may also combine or ++link a "work that uses the Library" with the Library to produce a ++work containing portions of the Library, and distribute that work ++under terms of your choice, provided that the terms permit ++modification of the work for the customer's own use and reverse ++engineering for debugging such modifications. ++ ++ You must give prominent notice with each copy of the work that the ++Library is used in it and that the Library and its use are covered by ++this License. You must supply a copy of this License. If the work ++during execution displays copyright notices, you must include the ++copyright notice for the Library among them, as well as a reference ++directing the user to the copy of this License. Also, you must do one ++of these things: ++ ++ a) Accompany the work with the complete corresponding ++ machine-readable source code for the Library including whatever ++ changes were used in the work (which must be distributed under ++ Sections 1 and 2 above); and, if the work is an executable linked ++ with the Library, with the complete machine-readable "work that ++ uses the Library", as object code and/or source code, so that the ++ user can modify the Library and then relink to produce a modified ++ executable containing the modified Library. (It is understood ++ that the user who changes the contents of definitions files in the ++ Library will not necessarily be able to recompile the application ++ to use the modified definitions.) ++ ++ b) Use a suitable shared library mechanism for linking with the ++ Library. A suitable mechanism is one that (1) uses at run time a ++ copy of the library already present on the user's computer system, ++ rather than copying library functions into the executable, and (2) ++ will operate properly with a modified version of the library, if ++ the user installs one, as long as the modified version is ++ interface-compatible with the version that the work was made with. ++ ++ c) Accompany the work with a written offer, valid for at ++ least three years, to give the same user the materials ++ specified in Subsection 6a, above, for a charge no more ++ than the cost of performing this distribution. ++ ++ d) If distribution of the work is made by offering access to copy ++ from a designated place, offer equivalent access to copy the above ++ specified materials from the same place. ++ ++ e) Verify that the user has already received a copy of these ++ materials or that you have already sent this user a copy. ++ ++ For an executable, the required form of the "work that uses the ++Library" must include any data and utility programs needed for ++reproducing the executable from it. However, as a special exception, ++the materials to be distributed need not include anything that is ++normally distributed (in either source or binary form) with the major ++components (compiler, kernel, and so on) of the operating system on ++which the executable runs, unless that component itself accompanies ++the executable. ++ ++ It may happen that this requirement contradicts the license ++restrictions of other proprietary libraries that do not normally ++accompany the operating system. Such a contradiction means you cannot ++use both them and the Library together in an executable that you ++distribute. ++ ++ 7. You may place library facilities that are a work based on the ++Library side-by-side in a single library together with other library ++facilities not covered by this License, and distribute such a combined ++library, provided that the separate distribution of the work based on ++the Library and of the other library facilities is otherwise ++permitted, and provided that you do these two things: ++ ++ a) Accompany the combined library with a copy of the same work ++ based on the Library, uncombined with any other library ++ facilities. This must be distributed under the terms of the ++ Sections above. ++ ++ b) Give prominent notice with the combined library of the fact ++ that part of it is a work based on the Library, and explaining ++ where to find the accompanying uncombined form of the same work. ++ ++ 8. You may not copy, modify, sublicense, link with, or distribute ++the Library except as expressly provided under this License. Any ++attempt otherwise to copy, modify, sublicense, link with, or ++distribute the Library is void, and will automatically terminate your ++rights under this License. However, parties who have received copies, ++or rights, from you under this License will not have their licenses ++terminated so long as such parties remain in full compliance. ++ ++ 9. You are not required to accept this License, since you have not ++signed it. However, nothing else grants you permission to modify or ++distribute the Library or its derivative works. These actions are ++prohibited by law if you do not accept this License. Therefore, by ++modifying or distributing the Library (or any work based on the ++Library), you indicate your acceptance of this License to do so, and ++all its terms and conditions for copying, distributing or modifying ++the Library or works based on it. ++ ++ 10. Each time you redistribute the Library (or any work based on the ++Library), the recipient automatically receives a license from the ++original licensor to copy, distribute, link with or modify the Library ++subject to these terms and conditions. You may not impose any further ++restrictions on the recipients' exercise of the rights granted herein. ++You are not responsible for enforcing compliance by third parties with ++this License. ++ ++ 11. If, as a consequence of a court judgment or allegation of patent ++infringement or for any other reason (not limited to patent issues), ++conditions are imposed on you (whether by court order, agreement or ++otherwise) that contradict the conditions of this License, they do not ++excuse you from the conditions of this License. If you cannot ++distribute so as to satisfy simultaneously your obligations under this ++License and any other pertinent obligations, then as a consequence you ++may not distribute the Library at all. For example, if a patent ++license would not permit royalty-free redistribution of the Library by ++all those who receive copies directly or indirectly through you, then ++the only way you could satisfy both it and this License would be to ++refrain entirely from distribution of the Library. ++ ++If any portion of this section is held invalid or unenforceable under any ++particular circumstance, the balance of the section is intended to apply, ++and the section as a whole is intended to apply in other circumstances. ++ ++It is not the purpose of this section to induce you to infringe any ++patents or other property right claims or to contest validity of any ++such claims; this section has the sole purpose of protecting the ++integrity of the free software distribution system which is ++implemented by public license practices. Many people have made ++generous contributions to the wide range of software distributed ++through that system in reliance on consistent application of that ++system; it is up to the author/donor to decide if he or she is willing ++to distribute software through any other system and a licensee cannot ++impose that choice. ++ ++This section is intended to make thoroughly clear what is believed to ++be a consequence of the rest of this License. ++ ++ 12. If the distribution and/or use of the Library is restricted in ++certain countries either by patents or by copyrighted interfaces, the ++original copyright holder who places the Library under this License may add ++an explicit geographical distribution limitation excluding those countries, ++so that distribution is permitted only in or among countries not thus ++excluded. In such case, this License incorporates the limitation as if ++written in the body of this License. ++ ++ 13. The Free Software Foundation may publish revised and/or new ++versions of the Lesser General Public License from time to time. ++Such new versions will be similar in spirit to the present version, ++but may differ in detail to address new problems or concerns. ++ ++Each version is given a distinguishing version number. If the Library ++specifies a version number of this License which applies to it and ++"any later version", you have the option of following the terms and ++conditions either of that version or of any later version published by ++the Free Software Foundation. If the Library does not specify a ++license version number, you may choose any version ever published by ++the Free Software Foundation. ++ ++ 14. If you wish to incorporate parts of the Library into other free ++programs whose distribution conditions are incompatible with these, ++write to the author to ask for permission. For software which is ++copyrighted by the Free Software Foundation, write to the Free ++Software Foundation; we sometimes make exceptions for this. Our ++decision will be guided by the two goals of preserving the free status ++of all derivatives of our free software and of promoting the sharing ++and reuse of software generally. ++ ++ NO WARRANTY ++ ++ 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO ++WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. ++EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR ++OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY ++KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE ++IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR ++PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE ++LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME ++THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. ++ ++ 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN ++WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY ++AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU ++FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR ++CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE ++LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING ++RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A ++FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF ++SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH ++DAMAGES. ++ ++ END OF TERMS AND CONDITIONS ++ ++ How to Apply These Terms to Your New Libraries ++ ++ If you develop a new library, and you want it to be of the greatest ++possible use to the public, we recommend making it free software that ++everyone can redistribute and change. You can do so by permitting ++redistribution under these terms (or, alternatively, under the terms of the ++ordinary General Public License). ++ ++ To apply these terms, attach the following notices to the library. It is ++safest to attach them to the start of each source file to most effectively ++convey the exclusion of warranty; and each file should have at least the ++"copyright" line and a pointer to where the full notice is found. ++ ++ ++ Copyright (C) ++ ++ This library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ This library 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 ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with this library; if not, write to the Free Software ++ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ++ ++Also add information on how to contact you by electronic and paper mail. ++ ++You should also get your employer (if you work as a programmer) or your ++school, if any, to sign a "copyright disclaimer" for the library, if ++necessary. Here is a sample; alter the names: ++ ++ Yoyodyne, Inc., hereby disclaims all copyright interest in the ++ library `Frob' (a library for tweaking knobs) written by James Random Hacker. ++ ++ , 1 April 1990 ++ Ty Coon, President of Vice ++ ++That's all there is to it! +diff --git a/services/plugins/resolutionKMS/Makefile.am b/services/plugins/resolutionKMS/Makefile.am +new file mode 100644 +index 0000000..4503dc6 +--- /dev/null ++++ b/services/plugins/resolutionKMS/Makefile.am +@@ -0,0 +1,37 @@ ++################################################################################ ++### Copyright (C) 2009-2016 VMware, Inc. All rights reserved. ++### ++### This program is free software; you can redistribute it and/or modify ++### it under the terms of version 2 of the GNU General Public License as ++### published by the Free Software Foundation. ++### ++### This program is distributed in the hope that it will be useful, ++### but WITHOUT ANY WARRANTY; without even the implied warranty of ++### MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++### GNU General Public License for more details. ++### ++### You should have received a copy of the GNU General Public License ++### along with this program; if not, write to the Free Software ++### Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++################################################################################ ++ ++plugindir = @VMSVC_PLUGIN_INSTALLDIR@ ++plugin_LTLIBRARIES = libresolutionKMS.la ++ ++libresolutionKMS_la_CPPFLAGS = ++libresolutionKMS_la_CPPFLAGS += @LIBUDEV_CFLAGS@ ++libresolutionKMS_la_CPPFLAGS += @PLUGIN_CPPFLAGS@ ++ ++libresolutionKMS_la_LDFLAGS = ++libresolutionKMS_la_LDFLAGS += @PLUGIN_LDFLAGS@ ++ ++libresolutionKMS_la_LIBADD = ++libresolutionKMS_la_LIBADD += @VMTOOLS_LIBS@ ++libresolutionKMS_la_LIBADD += @RESOLUTIONSET_LIBADD@ ++libresolutionKMS_la_LIBADD += $(top_builddir)/services/plugins/resolutionSet/libresolutionCommon.la ++ ++libresolutionKMS_la_SOURCES = ++libresolutionKMS_la_SOURCES += resolutionKMS.c ++ ++libresolutionKMS_la_DEPENDENCIES = ++libresolutionKMS_la_DEPENDENCIES += $(top_builddir)/services/plugins/resolutionSet/libresolutionCommon.la +diff --git a/services/plugins/resolutionKMS/resolutionKMS.c b/services/plugins/resolutionKMS/resolutionKMS.c +new file mode 100644 +index 0000000..6aff018 +--- /dev/null ++++ b/services/plugins/resolutionKMS/resolutionKMS.c +@@ -0,0 +1,465 @@ ++/********************************************************* ++ * Copyright (C) 2008-2016 VMware, Inc. All rights reserved. ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU Lesser General Public License as published ++ * by the Free Software Foundation version 2.1 and no later version. ++ * ++ * This program is distributed in the hope that it will be useful, but ++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY ++ * or FITNESS FOR A PARTICULAR PURPOSE. See the Lesser GNU General Public ++ * License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public License ++ * along with this program; if not, write to the Free Software Foundation, Inc., ++ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. ++ * ++ *********************************************************/ ++ ++/** ++ * @file resolutionKMS.c -- ++ * ++ * Plugin to communicate GUI topology to the vmwgfx drm device through a ++ * control node. This file is a modified version of resolutionSet.c ++ */ ++ ++#define G_LOG_DOMAIN "resolutionKMS" ++ ++#include ++#include ++#include ++ ++#include ++#include ++ ++#include "vmware.h" ++#include "debug.h" ++#include "rpcout.h" ++#include "str.h" ++#include "strutil.h" ++ ++#include "xdrutil.h" ++#include "vmware/guestrpc/tclodefs.h" ++#include "vmware/tools/plugin.h" ++#include "vmware/tools/utils.h" ++#include "../resolutionSet/resolutionCommon.h" ++#include "../resolutionSet/resolutionDL.h" ++ ++#include "vm_version.h" ++#include "embed_version.h" ++#include "vmtoolsd_version.h" ++VM_EMBED_VERSION(VMTOOLSD_VERSION_STRING); ++ ++/* ++ * The maximum number of capabilities we can set. ++ * ++ * See ResolutionSetCapabilities(). ++ */ ++#define RESOLUTION_SET_CAPABILITIES_MAX 5 ++ ++/* ++ * Global information about the communication state ++ */ ++typedef struct { ++ gboolean initialized; // Whether the plugin is already initialized. ++ int fd; // File descriptor to the DRM device. ++} KMSInfoType; ++ ++/* ++ * Internal global variables ++ */ ++KMSInfoType kmsInfo; ++ ++/* ++ * The name of the RPC channel we're using, e.g. TOOLS_DAEMON_NAME. Used by ++ * ResolutionSet_SetServerCapability() to determine which capability to set. ++ */ ++static const char *rpcChannelName = NULL; ++ ++/* ++ *----------------------------------------------------------------------------- ++ * ++ * ResolutionWriteToKernel -- ++ * ++ * Write GUI topology info to the drm device. ++ * ++ * Results: ++ * TRUE on success, FALSE on failure. ++ * ++ * Side effects: ++ * The drm device will send an uevent and expose the new ++ * topology. ++ * ++ *----------------------------------------------------------------------------- ++ */ ++ ++static gboolean ++ResolutionWriteToKernel(const struct drm_vmw_rect *rects, // IN: Screen rects ++ unsigned int num_rects) // IN: Number of ++ // rects ++{ ++ struct drm_vmw_update_layout_arg arg; ++ int ret; ++ ++ memset(&arg, 0, sizeof arg); ++ arg.num_outputs = num_rects; ++ arg.rects = (unsigned long) rects; ++ ++ ret = drmCommandWrite(kmsInfo.fd, DRM_VMW_UPDATE_LAYOUT, &arg, sizeof arg); ++ if (ret < 0) { ++ g_debug("%s: FAIL! Resolutionset write to kernel failed: %d\n", ++ __FUNCTION__, ret); ++ return FALSE; ++ } ++ ++ return TRUE; ++} ++ ++ ++/* ++ *----------------------------------------------------------------------------- ++ * ++ * ResolutionResolutionSetCB -- ++ * ++ * Handler for TCLO 'Resolution_Set'. ++ * Routine unmarshals RPC arguments and passes over to back-end ++ * ResolutionWriteToKernel(). ++ * ++ * Results: ++ * TRUE if we can reply, FALSE otherwise. ++ * ++ * Side effects: ++ * None. ++ * ++ *----------------------------------------------------------------------------- ++ */ ++ ++static gboolean ++ResolutionResolutionSetCB(RpcInData *data) // IN: The RPC data ++{ ++ struct drm_vmw_rect rect; ++ unsigned int index = 0; ++ gboolean retval = FALSE; ++ ++ if (!kmsInfo.initialized) { ++ g_debug("%s: FAIL! Request for resolution set but plugin is not initialized\n", ++ __FUNCTION__); ++ return RPCIN_SETRETVALS(data, "Invalid guest state: resolution set not initialized", FALSE); ++ } ++ ++ rect.x = 0; ++ rect.y = 0; ++ ++ /* parse the width and height */ ++ if (!StrUtil_GetNextUintToken(&rect.w, &index, data->args, " ")) { ++ goto invalid_arguments; ++ } ++ if (!StrUtil_GetNextUintToken(&rect.h, &index, data->args, "")) { ++ goto invalid_arguments; ++ } ++ ++ retval = ResolutionWriteToKernel(&rect, 1); ++ ++invalid_arguments: ++ return RPCIN_SETRETVALS(data, retval ? "" : "Invalid arguments", retval); ++} ++ ++ ++/* ++ *----------------------------------------------------------------------------- ++ * ++ * ResolutionDisplayTopologySetCB -- ++ * ++ * Handler for TCLO 'DisplayTopology_Set'. ++ * Routine unmarshals RPC arguments and passes over to back-end ++ * ResolutionWriteToKernel(). ++ * ++ * Results: ++ * TRUE if we can reply, FALSE otherwise. ++ * ++ * Side effects: ++ * None. ++ * ++ *----------------------------------------------------------------------------- ++ */ ++ ++static gboolean ++ResolutionDisplayTopologySetCB(RpcInData *data) ++{ ++ struct drm_vmw_rect *rects = NULL; ++ unsigned int count, i; ++ gboolean success = FALSE; ++ const char *p; ++ ++ if (!kmsInfo.initialized) { ++ g_debug("%s: FAIL! Request for topology set but plugin is not initialized\n", ++ __FUNCTION__); ++ RPCIN_SETRETVALS(data, "Invalid guest state: topology set not initialized", FALSE); ++ goto out; ++ } ++ ++ /* ++ * The argument string will look something like: ++ * [ , ] * count. ++ * ++ * e.g. ++ * 3 , 0 0 640 480 , 640 0 800 600 , 0 480 640 480 ++ */ ++ ++ if (sscanf(data->args, "%u", &count) != 1) { ++ return RPCIN_SETRETVALS(data, ++ "Invalid arguments. Expected \"count\"", ++ FALSE); ++ } ++ ++ rects = malloc(sizeof *rects * count); ++ if (!rects) { ++ RPCIN_SETRETVALS(data, ++ "Failed to alloc buffer for display info", ++ FALSE); ++ return FALSE; ++ } ++ ++ for (p = data->args, i = 0; i < count; i++) { ++ p = strchr(p, ','); ++ if (!p) { ++ RPCIN_SETRETVALS(data, ++ "Expected comma separated display list", ++ FALSE); ++ goto out; ++ } ++ p++; /* Skip past the , */ ++ ++ if (sscanf(p, " %d %d %d %d ", &rects[i].x, ++ &rects[i].y, &rects[i].w, &rects[i].h) != 4) { ++ RPCIN_SETRETVALS(data, ++ "Expected x, y, w, h in display entry", ++ FALSE); ++ goto out; ++ } ++ } ++ ++ success = ResolutionWriteToKernel(rects, count); ++ RPCIN_SETRETVALS(data, success ? "" : "ResolutionSetTopology failed", success); ++out: ++ free(rects); ++ return success; ++} ++ ++ ++/* ++ *----------------------------------------------------------------------------- ++ * ++ * ResolutionKMSServerCapability -- ++ * ++ * Sends the tools.capability.resolution_server RPC to the VMX. ++ * ++ * Side effects: ++ * None. ++ * ++ *----------------------------------------------------------------------------- ++ */ ++ ++static void ++ResolutionKMSServerCapability(RpcChannel *chan, // IN: The RPC channel. ++ unsigned int value) // IN: The value to send for ++ // the capability bit. ++{ ++ gchar *msg; ++ ++ if (!rpcChannelName) { ++ g_debug("Channel name is null, RPC not sent.\n"); ++ return; ++ } ++ ++ msg = g_strdup_printf("tools.capability.resolution_server %s %d", ++ rpcChannelName, ++ value); ++ if (!RpcChannel_Send(chan, msg, strlen(msg), NULL, NULL)) { ++ g_warning("%s: Unable to set tools.capability.resolution_server\n", ++ __FUNCTION__); ++ } ++ g_free(msg); ++} ++ ++ ++/* ++ *----------------------------------------------------------------------------- ++ * ++ * ResolutionKMSShutdown -- ++ * ++ * Cleans up internal data on shutdown. ++ * ++ * Side effects: ++ * None. ++ * ++ *----------------------------------------------------------------------------- ++ */ ++ ++static void ++ResolutionKMSShutdown(gpointer src, // IN: Unused. ++ ToolsAppCtx *ctx, // IN: The app context. ++ gpointer data) // IN: Unused. ++{ ++ if (kmsInfo.initialized && ctx && ctx->rpc && ctx->isVMware) { ++ ResolutionKMSServerCapability(ctx->rpc, 0); ++ } ++ ++ if (kmsInfo.initialized) { ++ resolutionDRMClose(kmsInfo.fd); ++ kmsInfo.initialized = FALSE; ++ } ++} ++ ++ ++/* ++ *----------------------------------------------------------------------------- ++ * ++ * ResolutionKMSCapabilities -- ++ * ++ * Cleans up internal data on shutdown. ++ * ++ * Results: ++ * An array of capabilities ++ * ++ * Side effects: ++ * None. ++ * ++ *----------------------------------------------------------------------------- ++ */ ++ ++static GArray * ++ResolutionKMSCapabilities(gpointer src, // IN: The source object. ++ ToolsAppCtx *ctx, // IN: The app context. ++ gboolean set, // IN: Whether setting or unsetting ++ // the capability. ++ gpointer data) // Unused. ++{ ++ /* The array of capabilities to return to the tools service. */ ++ ToolsAppCapability capabilityArray[RESOLUTION_SET_CAPABILITIES_MAX]; ++ ++ /* The next unused entry in the capabilities array. */ ++ unsigned int capabilityCount = 0; ++ ++ g_debug("%s: enter\n", __FUNCTION__); ++ ++ /* ++ * We must register display_topology_set before resolution_set to avoid ++ * a race condition in the host. See bug 472343. ++ */ ++ ++ /* ++ * We use a value of '2' here because, for historical reasons, the ++ * Workstation/Fusion UI will treat a value of 1 for this capability ++ * as unsupported. See bug 149541. ++ */ ++ capabilityArray[capabilityCount].type = TOOLS_CAP_OLD; ++ capabilityArray[capabilityCount].name = "display_topology_set"; ++ capabilityArray[capabilityCount].index = 0; ++ capabilityArray[capabilityCount].value = set ? 2 : 0; ++ capabilityCount++; ++ ++ capabilityArray[capabilityCount].type = TOOLS_CAP_OLD; ++ capabilityArray[capabilityCount].name = "display_global_offset"; ++ capabilityArray[capabilityCount].index = 0; ++ capabilityArray[capabilityCount].value = set ? 1 : 0; ++ capabilityCount++; ++ ++ capabilityArray[capabilityCount].type = TOOLS_CAP_OLD; ++ capabilityArray[capabilityCount].name = "resolution_set"; ++ capabilityArray[capabilityCount].index = 0; ++ capabilityArray[capabilityCount].value = set ? 1 : 0; ++ capabilityCount++; ++ ++ /* ++ * Send the resolution_server RPC to the VMX. ++ * ++ * XXX: We need to send this ourselves, instead of including it in the ++ * capability array, because the resolution_server RPC includes the ++ * name of the RPC channel that the VMX should use when sending ++ * resolution set RPCs as an argument. ++ */ ++ ++ if (kmsInfo.initialized && ctx && ctx->rpc && ctx->isVMware) { ++ ResolutionKMSServerCapability(ctx->rpc, set ? 1:0); ++ } ++ ++ ASSERT(capabilityCount <= RESOLUTION_SET_CAPABILITIES_MAX); ++ ++ return VMTools_WrapArray(capabilityArray, ++ sizeof *capabilityArray, ++ capabilityCount); ++} ++ ++ ++/* ++ *----------------------------------------------------------------------------- ++ * ++ * ToolsOnLoad -- ++ * ++ * Plugin entry point ++ * ++ * Results: ++ * The registration data. ++ * ++ * Side effects: ++ * Initializes internal plugin state. ++ * ++ *----------------------------------------------------------------------------- ++ */ ++ ++TOOLS_MODULE_EXPORT ToolsPluginData * ++ToolsOnLoad(ToolsAppCtx *ctx) ++{ ++ RpcChannelCallback rpcs[] = { ++ { "Resolution_Set", &ResolutionResolutionSetCB }, ++ { "DisplayTopology_Set", &ResolutionDisplayTopologySetCB }, ++ }; ++ ++ static ToolsPluginData regData = { ++ "resolutionKMS", ++ NULL, ++ NULL ++ }; ++ ++ ToolsPluginSignalCb sigs[] = { ++ { TOOLS_CORE_SIG_CAPABILITIES, ResolutionKMSCapabilities, ®Data }, ++ { TOOLS_CORE_SIG_SHUTDOWN, ResolutionKMSShutdown, ®Data } ++ }; ++ ++ ToolsAppReg regs[] = { ++ { TOOLS_APP_GUESTRPC, NULL }, ++ { TOOLS_APP_SIGNALS, VMTools_WrapArray(sigs, sizeof *sigs, ARRAYSIZE(sigs)) } ++ }; ++ ++ /* ++ * If we aren't running in a VM (e.g., running in bootcamp natively on ++ * a Mac), then just return NULL. ++ */ ++ if (!ctx->isVMware) { ++ return NULL; ++ } ++ ++ kmsInfo.fd = resolutionCheckForKMS(ctx); ++ if (kmsInfo.fd < 0) { ++ return NULL; ++ } ++ kmsInfo.initialized = TRUE; ++ ++ /* ++ * Save the RPC channel name from the ToolsAppCtx so that we can use it later ++ * in calls to ResolutionSetServerCapability(). ++ */ ++ ++ if (strcmp(ctx->name, VMTOOLS_GUEST_SERVICE) == 0) { ++ rpcChannelName = TOOLS_DAEMON_NAME; ++ } else if (strcmp(ctx->name, VMTOOLS_USER_SERVICE) == 0) { ++ rpcChannelName = TOOLS_DND_NAME; ++ } else { ++ NOT_REACHED(); ++ } ++ ++ regs[0].data = VMTools_WrapArray(rpcs, sizeof *rpcs, ARRAYSIZE(rpcs)); ++ regData.regs = VMTools_WrapArray(regs, sizeof *regs, ARRAYSIZE(regs)); ++ return ®Data; ++} +diff --git a/services/plugins/resolutionSet/Makefile.am b/services/plugins/resolutionSet/Makefile.am +index 3d8dbc4..b3cf81e 100644 +--- a/services/plugins/resolutionSet/Makefile.am ++++ b/services/plugins/resolutionSet/Makefile.am +@@ -16,6 +16,9 @@ + ################################################################################ + + plugindir = @VMUSR_PLUGIN_INSTALLDIR@ ++noinst_LTLIBRARIES = libresolutionCommon.la ++ ++if HAVE_X11 + plugin_LTLIBRARIES = libresolutionSet.la + + libresolutionSet_la_CPPFLAGS = +@@ -30,10 +33,27 @@ libresolutionSet_la_LIBADD = + libresolutionSet_la_LIBADD += @COMMON_XLIBS@ + libresolutionSet_la_LIBADD += @GTK_LIBS@ + libresolutionSet_la_LIBADD += @VMTOOLS_LIBS@ ++libresolutionSet_la_LIBADD += @RESOLUTIONSET_LIBADD@ ++libresolutionSet_la_LIBADD += libresolutionCommon.la + + libresolutionSet_la_SOURCES = + libresolutionSet_la_SOURCES += libvmwarectrl.c + libresolutionSet_la_SOURCES += resolutionSet.c + libresolutionSet_la_SOURCES += resolutionX11.c + libresolutionSet_la_SOURCES += resolutionRandR12.c ++endif ++ ++libresolutionCommon_la_CPPFLAGS = ++libresolutionCommon_la_CPPFLAGS += @PLUGIN_CPPFLAGS@ ++libresolutionCommon_la_CPPFLAGS += @LIBUDEV_CFLAGS@ ++ ++libresolutionCommon_la_SOURCES = ++libresolutionCommon_la_SOURCES += resolutionCommon.c ++libresolutionCommon_la_SOURCES += resolutionCommon.h ++libresolutionCommon_la_SOURCES += resolutionDL.c ++libresolutionCommon_la_SOURCES += resolutionDL.h ++libresolutionCommon_la_LDFLAGS = ++libresolutionCommon_la_LDFLAGS += @PLUGIN_LDFLAGS@ + ++libresolutionCommon_la_LIBADD = ++libresolutionCommon_la_LIBADD += @LIBUDEV_LIBS@ +diff --git a/services/plugins/resolutionSet/resolutionCommon.c b/services/plugins/resolutionSet/resolutionCommon.c +new file mode 100644 +index 0000000..9a076e3 +--- /dev/null ++++ b/services/plugins/resolutionSet/resolutionCommon.c +@@ -0,0 +1,430 @@ ++/********************************************************* ++ * Copyright (C) 2016 VMware, Inc. All rights reserved. ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU Lesser General Public License as published ++ * by the Free Software Foundation version 2.1 and no later version. ++ * ++ * This program is distributed in the hope that it will be useful, but ++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY ++ * or FITNESS FOR A PARTICULAR PURPOSE. See the Lesser GNU General Public ++ * License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public License ++ * along with this program; if not, write to the Free Software Foundation, Inc., ++ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. ++ * ++ *********************************************************/ ++/* Authors: ++ * Thomas Hellstrom ++ */ ++ ++#define G_LOG_DOMAIN "resolutionCommon" ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "resolutionDL.h" ++#include "vmware/tools/plugin.h" ++#include "vmware/tools/utils.h" ++#include "resolutionCommon.h" ++ ++#ifdef ENABLE_RESOLUTIONKMS ++ ++/* The DRM device we are looking for */ ++#define RESOLUTION_VENDOR "0x15ad" ++#define RESOLUTION_DEVICE "0x0405" ++ ++/* Required DRM version for resolutionKMS */ ++#define RESOLUTION_DRM_MAJOR 2 ++#define RESOLUTION_DRM_MINOR 12 ++ ++/* Required Xorg driver version for resolutionKMS default on */ ++#define RESOLUTION_XORG_MAJOR 13 ++#define RESOLUTION_XORG_MINOR 2 ++ ++/* Recognition token for Xorg driver version scanner */ ++#define RESOLUTION_XORG_VERSTRING "version=" ++ ++/* ++ * Xorg driver file names to scan for. Only the first found will be ++ * scanned for version info. ++ */ ++static const char *driverNames[]= { ++ "/usr/lib64/xorg/modules/drivers/vmware_drv.so", ++ "/usr/lib/xorg/modules/drivers/vmware_drv.so" ++}; ++ ++static const int numDriverNames = 2; ++ ++/* ++ *----------------------------------------------------------------------------- ++ * ++ * resolutionOpenDRM -- ++ * ++ * Opens a file descriptor on the indicated node to the first SVGA2 device. ++ * ++ * Results: ++ * Returns a positive file descriptor on success. Otherwise returns -1. ++ * ++ * Side effects: ++ * None. ++ * ++ *----------------------------------------------------------------------------- ++ */ ++static int ++resolutionOpenDRM(const char *node) // IN: Device node base name. ++{ ++ struct udev *udev; ++ struct udev_enumerate *enumerate; ++ struct udev_list_entry *devices, *devListEntry; ++ struct udev_device *dev; ++ int fd = -1; ++ const char *devNode = NULL; ++ ++ udev = udev_new(); ++ if (!udev) ++ return -1; ++ ++ /* ++ * Udev error return codes that are not caught immediately are ++ * typically caught in the input argument check in the udev ++ * function calls following the failing call! ++ */ ++ enumerate = udev_enumerate_new(udev); ++ if (udev_enumerate_add_match_subsystem(enumerate, "drm")) ++ goto outErr; ++ if (udev_enumerate_add_match_property(enumerate, "DEVTYPE", "drm_minor")) ++ goto outErr; ++ if (udev_enumerate_scan_devices(enumerate)) ++ goto outErr; ++ ++ devices = udev_enumerate_get_list_entry(enumerate); ++ udev_list_entry_foreach(devListEntry, devices) { ++ const char *path, *vendor, *device; ++ struct udev_device *parent; ++ ++ path = udev_list_entry_get_name(devListEntry); ++ if (!path) ++ continue; ++ if (!strstr(path, node)) ++ continue; ++ ++ dev = udev_device_new_from_syspath(udev, path); ++ if (!dev) ++ goto outErr; ++ ++ parent = udev_device_get_parent_with_subsystem_devtype(dev, ++ "pci", ++ NULL); ++ if (!parent) ++ goto skipCheck; ++ ++ vendor = udev_device_get_sysattr_value(parent, "vendor"); ++ device = udev_device_get_sysattr_value(parent, "device"); ++ if (!vendor || !device) ++ goto skipCheck; ++ ++ if (strcmp(vendor, RESOLUTION_VENDOR) || ++ strcmp(device, RESOLUTION_DEVICE)) ++ goto skipCheck; ++ ++ devNode = udev_device_get_devnode(dev); ++ if (!devNode) ++ goto outFound; ++ ++ fd = open(devNode, O_RDWR); ++ udev_device_unref(dev); ++ break; ++ ++skipCheck: ++ udev_device_unref(dev); ++ } ++ ++ udev_enumerate_unref(enumerate); ++ udev_unref(udev); ++ ++ return fd; ++ ++ outFound: ++ udev_device_unref(dev); ++ outErr: ++ udev_enumerate_unref(enumerate); ++ udev_unref(udev); ++ ++ return -1; ++} ++ ++/* ++ *----------------------------------------------------------------------------- ++ * ++ * resolutionDRMCheckVersion -- ++ * ++ * Check that the drm version supports GUI topology communication. ++ * ++ * Checks that the DRM device supports setting GUI topology from the ++ * control node, and also that the topology is communicated on the ++ * modesetting connectors. ++ * ++ * Results: ++ * 0 if DRM device is usable for communicating GUI topology. ++ * -1 otherwise. ++ * ++ * Side effects: ++ * None. ++ * ++ *----------------------------------------------------------------------------- ++ */ ++static int ++resolutionDRMCheckVersion(int fd) // IN: An open DRM file descriptor. ++{ ++ drmVersionPtr ver = drmGetVersion(fd); ++ ++ if (!ver) { ++ g_debug("%s: Failed to get DRM version.\n", __func__); ++ return -1; ++ } ++ ++ if (ver->version_major != RESOLUTION_DRM_MAJOR || ++ ver->version_minor < RESOLUTION_DRM_MINOR) { ++ g_debug("%s: Insufficient DRM version %d.%d for resolutionKMS.\n", ++ __func__, ver->version_major, ver->version_minor); ++ drmFreeVersion(ver); ++ return -1; ++ } ++ ++ drmFreeVersion(ver); ++ return 0; ++} ++ ++ ++/* ++ *----------------------------------------------------------------------------- ++ * ++ * resolutionDRMRPrimaryCheckOpen -- ++ * ++ * First tries to open a render node to DRM, and if that fails opens a ++ * primary node, and drops master. Then checks that drm supports GUI ++ * topology communication. ++ * ++ * Results: ++ * If succesful returns a positive open file descriptor. Otherwise ++ * returns -1. ++ * ++ * Side effects: ++ * May temporarily become drm master if render nodes are not available, ++ * and thus race with the X server. ++ * ++ *----------------------------------------------------------------------------- ++ */ ++static int ++resolutionDRMRPrimaryCheckOpen(void) ++{ ++ int fd = -1; ++ ++ fd = resolutionOpenDRM("renderD"); ++ if (fd < 0) { ++ g_debug("%s: Failed to open DRM render node.\n", __func__); ++ fd = resolutionOpenDRM("card"); ++ if (fd >= 0) ++ (void) drmDropMaster(fd); ++ } ++ if (fd < 0) { ++ g_debug("%s: Failed to open DRM card node.\n", __func__); ++ goto outErr; ++ } ++ ++ if (!resolutionDRMCheckVersion(fd)) { ++ return fd; ++ } ++ ++ close(fd); ++ outErr: ++ return -1; ++} ++ ++ ++/* ++ *----------------------------------------------------------------------------- ++ * ++ * resolutionCheckForKMS -- ++ * ++ * Checks whether the vmwgfx DRM is present and supports exposing ++ * layout information through connector properties and preferred modes. ++ * ++ * Results: ++ * If succesful returns a positive number representing an open file ++ * descriptor to the node indicated by the control argument. If ++ * unsuccessful returns -1. ++ * ++ * Side effects: ++ * Opens a file to DRM. The file descriptor should be closed with ++ * resolutionDRMClose() when needed. ++ * ++ *----------------------------------------------------------------------------- ++ */ ++int ++resolutionCheckForKMS(ToolsAppCtx *ctx) // IN: The ToolsAppCtx for ++ // configuration db access. ++{ ++ GError *err = NULL; ++ gboolean doResolutionKMS; ++ int fd; ++ ++ doResolutionKMS = g_key_file_get_boolean(ctx->config, "resolutionKMS", ++ "enable", &err); ++ if (err) { ++ /* ++ * If there is nothing in the configuration file, require ++ * at least Xorg driver version 13.2.0, which has the autolayout ++ * feature, to enable resolutionKMS. ++ */ ++ int major, minor, level; ++ g_clear_error(&err); ++ doResolutionKMS = FALSE; ++ if (!resolutionXorgDriverVersion(numDriverNames, driverNames, ++ RESOLUTION_XORG_VERSTRING, &major, ++ &minor, &level) && ++ (major > RESOLUTION_XORG_MAJOR || ++ (major == RESOLUTION_XORG_MAJOR && ++ minor >= RESOLUTION_XORG_MINOR))) { ++ doResolutionKMS = TRUE; ++ g_debug("%s: ResolutionKMS enabled based on Xorg driver version.\n", ++ __func__); ++ } else { ++ g_debug("%s: ResolutionKMS disabled. (No configuration).\n", ++ __func__); ++ doResolutionKMS = FALSE; ++ } ++ } else { ++ g_debug("%s: ResolutionKMS %s using configuration file info.\n", ++ __func__, (doResolutionKMS) ? "enabled" : "disabled"); ++ } ++ ++ if (!doResolutionKMS) ++ return -1; ++ ++ if (resolutionDLOpen()) { ++ g_warning("%s: Failed to find needed system libraries for " ++ "resolutionKMS.\n", __func__); ++ return -1; ++ } else { ++ g_message("%s: dlopen succeeded.\n", __func__); ++ } ++ ++ fd = resolutionDRMRPrimaryCheckOpen(); ++ ++ if (fd < 0) ++ g_warning("%s: No system support for resolutionKMS.\n", __func__); ++ else ++ g_message("%s: System support available for resolutionKMS.\n", ++ __func__); ++ ++ return fd; ++} ++ ++/* ++ *----------------------------------------------------------------------------- ++ * ++ * resolutionDRMClose -- ++ * ++ * Scans for VMWare Xorg driver files and tries to determine the Xorg ++ * driver version. ++ * ++ * Results: ++ * If succesful returns zero and outputs the driver version in the ++ * parameters major, minor and level. If not successful, returns -1. ++ * ++ * Side effects: ++ * None. ++ * ++ *----------------------------------------------------------------------------- ++ */ ++void ++resolutionDRMClose(int fd) ++{ ++ close(fd); ++ resolutionDLClose(); ++} ++ ++#endif /* ENABLE_RESOLUTIONKMS */ ++ ++/* ++ *----------------------------------------------------------------------------- ++ * ++ * resolutionXorgDriverVersion -- ++ * ++ * Scans for VMWare Xorg driver files and tries to determine the Xorg ++ * driver version. ++ * ++ * Results: ++ * If succesful returns zero and outputs the driver version in the ++ * parameters major, minor and level. If not successful, returns -1. ++ * ++ * Side effects: ++ * None. ++ * ++ *----------------------------------------------------------------------------- ++ */ ++int ++resolutionXorgDriverVersion(int numPaths, // IN: Number of strings ++ // in paths. ++ const char *paths[], // IN: Possible driver ++ // paths. ++ const char versionString[], // IN: Version token. ++ int *major, // OUT: Major version # ++ int *minor, // OUT: Minor version # ++ int *level) // OUT: Patchlevel ++ // version # ++{ ++ FILE *driver = NULL; ++ const char *curMatch; ++ char curFileChar; ++ int i; ++ ++ g_debug("%s: Scanning for VMWare Xorg drivers.\n", __func__); ++ for(i = 0; i < numPaths; ++i) { ++ g_debug("%s: Looking for \"%s\".\n", __func__, paths[i]); ++ driver = fopen(paths[i], "r"); ++ if (driver) ++ break; ++ } ++ ++ if (!driver) { ++ g_debug("%s: No driver found.\n", __func__); ++ return -1; ++ } ++ ++ g_debug("%s: Driver found. Looking for version info.\n", __func__); ++ curMatch = versionString; ++ while (*curMatch) { ++ if (feof(driver)) ++ goto outNotFound; ++ ++ curFileChar = fgetc(driver); ++ if (curFileChar == *curMatch) { ++ curMatch++; ++ continue; ++ } else if (curMatch != versionString) { ++ curMatch = versionString; ++ (void) ungetc(curFileChar, driver); ++ } ++ } ++ ++ if (fscanf(driver, "%d.%d.%d", major, minor, level) != 3) ++ goto outNotFound; ++ ++ fclose(driver); ++ g_debug("%s: Version info found: %d.%d.%d\n", __func__, *major, *minor, ++ *level); ++ return 0; ++ ++ outNotFound: ++ fclose(driver); ++ g_debug("%s: No version info found.\n", __func__); ++ return -1; ++} +diff --git a/services/plugins/resolutionSet/resolutionCommon.h b/services/plugins/resolutionSet/resolutionCommon.h +new file mode 100644 +index 0000000..6565190 +--- /dev/null ++++ b/services/plugins/resolutionSet/resolutionCommon.h +@@ -0,0 +1,53 @@ ++/********************************************************* ++ * Copyright (C) 2016 VMware, Inc. All rights reserved. ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU Lesser General Public License as published ++ * by the Free Software Foundation version 2.1 and no later version. ++ * ++ * This program is distributed in the hope that it will be useful, but ++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY ++ * or FITNESS FOR A PARTICULAR PURPOSE. See the Lesser GNU General Public ++ * License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public License ++ * along with this program; if not, write to the Free Software Foundation, Inc., ++ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. ++ * ++ *********************************************************/ ++/* Authors: ++ * Thomas Hellstrom ++ */ ++ ++#ifndef _RESOLUTION_COMMON_H_ ++#define _RESOLUTION_COMMON_H_ ++ ++#define INCLUDE_ALLOW_USERLEVEL ++#define INCLUDE_ALLOW_DISTRIBUTE ++#include "includeCheck.h" ++#include "vmware/tools/plugin.h" ++#ifdef ENABLE_RESOLUTIONKMS ++ ++int resolutionCheckForKMS(ToolsAppCtx *ctx); ++void resolutionDRMClose(int fd); ++ ++#else ++ ++static inline int resolutionCheckForKMS(ToolsAppCtx *ctx) ++{ ++ return -1; ++} ++ ++static inline void resolutionDRMClose(int fd) {} ++ ++#endif /* !ENABLE_RESOLUTIONKMS */ ++ ++int ++resolutionXorgDriverVersion(int numPaths, ++ const char *paths[], ++ const char versionString[], ++ int *major, ++ int *minor, ++ int *level); ++ ++#endif /* _RESOLUTION_COMMON_H_ */ +diff --git a/services/plugins/resolutionSet/resolutionDL.c b/services/plugins/resolutionSet/resolutionDL.c +new file mode 100644 +index 0000000..5ec0abb +--- /dev/null ++++ b/services/plugins/resolutionSet/resolutionDL.c +@@ -0,0 +1,206 @@ ++/********************************************************* ++ * Copyright (C) 2016 VMware, Inc. All rights reserved. ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU Lesser General Public License as published ++ * by the Free Software Foundation version 2.1 and no later version. ++ * ++ * This program is distributed in the hope that it will be useful, but ++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY ++ * or FITNESS FOR A PARTICULAR PURPOSE. See the Lesser GNU General Public ++ * License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public License ++ * along with this program; if not, write to the Free Software Foundation, Inc., ++ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. ++ * ++ *********************************************************/ ++/* Authors: ++ * Thomas Hellstrom ++ */ ++ ++#ifdef ENABLE_RESOLUTIONKMS ++#ifndef HAVE_LIBUDEV ++ ++#include "resolutionDL.h" ++#include "vmware.h" ++#include ++#include ++#include ++ ++#define G_LOG_DOMAIN "resolutionCommon" ++#include "vmware/tools/plugin.h" ++#include "vmware/tools/utils.h" ++ ++ ++struct FuncToResolv { ++ size_t offset; ++ const char *name; ++}; ++ ++#define UDEV_RESOLV(_name) \ ++ {.offset = offsetof(struct Udev1Interface, _name), \ ++ .name = "udev"#_name} ++ ++#define LIBDRM_RESOLV(_name) \ ++ {.offset = offsetof(struct Drm2Interface, _name), \ ++ .name = "drm"#_name} ++ ++ ++static struct FuncToResolv udev1Table[] = { ++ UDEV_RESOLV(_device_get_devnode), ++ UDEV_RESOLV(_device_get_parent_with_subsystem_devtype), ++ UDEV_RESOLV(_device_get_sysattr_value), ++ UDEV_RESOLV(_device_new_from_syspath), ++ UDEV_RESOLV(_device_unref), ++ UDEV_RESOLV(_enumerate_add_match_property), ++ UDEV_RESOLV(_enumerate_add_match_subsystem), ++ UDEV_RESOLV(_enumerate_get_list_entry), ++ UDEV_RESOLV(_enumerate_new), ++ UDEV_RESOLV(_enumerate_scan_devices), ++ UDEV_RESOLV(_enumerate_unref), ++ UDEV_RESOLV(_list_entry_get_name), ++ UDEV_RESOLV(_list_entry_get_next), ++ UDEV_RESOLV(_new), ++ UDEV_RESOLV(_unref) ++}; ++ ++static struct FuncToResolv drm2Table[] = { ++ LIBDRM_RESOLV(GetVersion), ++ LIBDRM_RESOLV(FreeVersion), ++ LIBDRM_RESOLV(DropMaster), ++ LIBDRM_RESOLV(CommandWrite) ++}; ++ ++struct Udev1Interface *udevi = NULL; ++struct Drm2Interface *drmi = NULL; ++ ++static void *dlhandle; ++ ++/* ++ *----------------------------------------------------------------------------- ++ * ++ * resolutionDLClose -- ++ * ++ * Removes any dynamic library reference and frees any resource ++ * allocated by resolutionDLOpen. ++ * ++ * Side effects: ++ * None. ++ * ++ *----------------------------------------------------------------------------- ++ */ ++void ++resolutionDLClose(void) ++{ ++ if (udevi) { ++ free(udevi); ++ udevi = NULL; ++ } ++ ++ if (drmi) { ++ free(drmi); ++ drmi = NULL; ++ } ++ ++ if (dlhandle) { ++ dlclose(dlhandle); ++ dlhandle = NULL; ++ } ++} ++ ++/* ++ *----------------------------------------------------------------------------- ++ * ++ * resolutionDLResolve -- ++ * ++ * Tries to open and resolve needed symbols of a single shared library. ++ * ++ * Results: ++ * If succesful returns zero, otherwise returns -1. ++ * ++ * Side effects: ++ * None. ++ * ++ *----------------------------------------------------------------------------- ++ */ ++static int ++resolutionDLResolve(void **ptr, // OUT: pointer to ++ // function table. ++ size_t size, // IN: Size of ft. ++ const char name[], // IN: Library name. ++ const struct FuncToResolv table[], // IN: Table of name- ++ // offset pairs ++ int numEntries) // IN: Num entries in ++ // table. ++{ ++ void **func_ptr; ++ int i; ++ ++ if (*ptr) ++ return 0; ++ ++ *ptr = malloc(size); ++ if (!*ptr) ++ return -1; ++ ++ dlhandle = dlopen(name, RTLD_NOW); ++ if (!dlhandle) { ++ g_debug("%s: Failed to open shared library \"%s\".\n", __func__, ++ name); ++ goto out_err; ++ } ++ ++ for (i = 0; i < numEntries; ++i) { ++ func_ptr = (void *) ((unsigned long) *ptr + table[i].offset); ++ *func_ptr = dlsym(dlhandle, table[i].name); ++ if (!*func_ptr) { ++ g_debug("%s: Failed to resolve %s symbol \"%s\".\n", __func__, ++ name,table[i].name); ++ goto out_err; ++ } ++ } ++ ++ return 0; ++ ++ out_err: ++ resolutionDLClose(); ++ ++ return -1; ++} ++ ++/* ++ *----------------------------------------------------------------------------- ++ * ++ * resolutionDLOpen -- ++ * ++ * Tries to open and create a reference to distribution shared libraries ++ * needed for the resolutionKMS functionality. ++ * ++ * Results: ++ * If succesful returns zero, otherwise returns -1. ++ * ++ * Side effects: ++ * None. ++ * ++ *----------------------------------------------------------------------------- ++ */ ++int ++resolutionDLOpen(void) ++{ ++ /* We support libudev major versions 0 and 1 for now. */ ++ if (resolutionDLResolve((void **)&udevi, sizeof(*udevi), "libudev.so.1", ++ udev1Table, ARRAYSIZE(udev1Table)) && ++ resolutionDLResolve((void **)&udevi, sizeof(*udevi), "libudev.so.0", ++ udev1Table, ARRAYSIZE(udev1Table))) ++ return -1; ++ ++ if (resolutionDLResolve((void **)&drmi, sizeof(*drmi), "libdrm.so.2", ++ drm2Table, ARRAYSIZE(drm2Table))) ++ return -1; ++ ++ return 0; ++} ++ ++#endif /* !HAVE_LIBUDEV */ ++#endif /* ENABLE_RESOLUTIONKMS */ +diff --git a/services/plugins/resolutionSet/resolutionDL.h b/services/plugins/resolutionSet/resolutionDL.h +new file mode 100644 +index 0000000..f0d8c6d +--- /dev/null ++++ b/services/plugins/resolutionSet/resolutionDL.h +@@ -0,0 +1,217 @@ ++/********************************************************* ++ * Copyright (C) 2016 VMware, Inc. All rights reserved. ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU Lesser General Public License as published ++ * by the Free Software Foundation version 2.1 and no later version. ++ * ++ * This program is distributed in the hope that it will be useful, but ++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY ++ * or FITNESS FOR A PARTICULAR PURPOSE. See the Lesser GNU General Public ++ * License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public License ++ * along with this program; if not, write to the Free Software Foundation, Inc., ++ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. ++ * ++ *********************************************************/ ++/* Authors: ++ * Thomas Hellstrom ++ */ ++ ++#ifndef _RESOLUTION_DL_H_ ++#define _RESOLUTION_DL_H_ ++#ifdef ENABLE_RESOLUTIONKMS ++ ++#define INCLUDE_ALLOW_USERLEVEL ++#define INCLUDE_ALLOW_DISTRIBUTE ++#include "includeCheck.h" ++ ++#ifndef HAVE_LIBUDEV ++ ++#include ++ ++struct udev; ++struct udev_device; ++struct udev_enumerate; ++ ++/* ++ * This struct holds the function pointers we use in libudev.1. Libudev is ++ * Lgpl 2.1 (or later) licensed, and according to lgpl 2.1, section 5, while ++ * we use materials copied from header files, we restrict ourselves to ++ * data structure layouts and small macros and thus, while this should be ++ * considered a derivative work, the use of the object file is unrestricted. ++ * An executable linked with libudev is however subject to lgpl license ++ * restrictions. ++ */ ++struct Udev1Interface { ++ const char * ++ (*_device_get_devnode)(struct udev_device *); ++ struct udev_device * ++ (*_device_get_parent_with_subsystem_devtype)(struct udev_device *, ++ const char *, const char *); ++ const char * ++ (*_device_get_sysattr_value)(struct udev_device *, const char *); ++ struct udev_device * ++ (*_device_new_from_syspath)(struct udev *, const char *); ++ struct udev_device * ++ (*_device_unref)(struct udev_device *); ++ int ++ (*_enumerate_add_match_property)(struct udev_enumerate *,const char *, ++ const char *); ++ int ++ (*_enumerate_add_match_subsystem)(struct udev_enumerate *,const char *); ++ struct udev_list_entry * ++ (*_enumerate_get_list_entry)(struct udev_enumerate *); ++ struct udev_enumerate * ++ (*_enumerate_new)(struct udev *udev); ++ int ++ (*_enumerate_scan_devices)(struct udev_enumerate *); ++ struct udev_enumerate * ++ (*_enumerate_unref)(struct udev_enumerate *); ++ const char * ++ (*_list_entry_get_name)(struct udev_list_entry *); ++ struct udev_list_entry * ++ (*_list_entry_get_next)(struct udev_list_entry *); ++ struct udev * ++ (*_new)(void); ++ struct udev * ++ (*_unref)(struct udev *); ++}; ++ ++#define udevi_list_entry_foreach(_udevi, list_entry, first_entry) \ ++ for (list_entry = first_entry; \ ++ list_entry != NULL; \ ++ list_entry = (_udevi)->_list_entry_get_next(list_entry)) ++ ++/* ++ * This struct is originally defined in xf86drm.h which is MIT licenced. ++ * However, this should not be considered a substantial part of the software, ++ * and this struct is not subject to the license header of this file. ++ */ ++typedef struct _drmVersion { ++ int version_major; /* Major version */ ++ int version_minor; /* Minor version */ ++ int version_patchlevel; /* Patch level */ ++ int name_len; /* Length of name buffer */ ++ char *name; /* Name of driver */ ++ int date_len; /* Length of date buffer */ ++ char *date; /* User-space buffer to hold date */ ++ int desc_len; /* Length of desc buffer */ ++ char *desc; /* User-space buffer to hold desc */ ++} drmVersion, *drmVersionPtr; ++ ++#define DRM_VMW_UPDATE_LAYOUT 20 ++ ++/* ++ * These structs are originally defined in vmwgfx_drm.h, which is dual ++ * MIT and GPLv2 licenced. However, VMWare Inc. owns the copyright and it's ++ * should not be considered a substantial part of the software. ++ * However this struct is not subject to the license header of this file. ++ */ ++/** ++ * struct drm_vmw_rect ++ * ++ * Defines a rectangle. Used in the overlay ioctl to define ++ * source and destination rectangle. ++ */ ++ ++struct drm_vmw_rect { ++ int32_t x; ++ int32_t y; ++ uint32_t w; ++ uint32_t h; ++}; ++ ++/** ++ * struct drm_vmw_update_layout_arg ++ * ++ * @num_outputs: number of active connectors ++ * @rects: pointer to array of drm_vmw_rect cast to an uint64_t ++ * ++ * Input argument to the DRM_VMW_UPDATE_LAYOUT Ioctl. ++ */ ++struct drm_vmw_update_layout_arg { ++ uint32_t num_outputs; ++ uint32_t pad64; ++ uint64_t rects; ++}; ++ ++/* ++ * This struct holds the function pointers we use in libdrm.2. The ++ * libdrm API is MIT licenced and what we do here should not be considered ++ * a substantial part of the software: ++ * However this struct is not subject to the license header of this file. ++ */ ++struct Drm2Interface { ++ drmVersionPtr (*GetVersion)(int fd); ++ void (*FreeVersion)(drmVersionPtr); ++ int (*DropMaster)(int fd); ++ int (*CommandWrite)(int fd, unsigned long drmCommandIndex, void *data, ++ unsigned long size); ++}; ++ ++extern struct Udev1Interface *udevi; ++extern struct Drm2Interface *drmi; ++ ++void resolutionDLClose(void); ++int resolutionDLOpen(void); ++ ++#define udev_device_get_devnode \ ++ udevi->_device_get_devnode ++#define udev_device_get_parent_with_subsystem_devtype \ ++ udevi->_device_get_parent_with_subsystem_devtype ++#define udev_device_get_sysattr_value \ ++ udevi->_device_get_sysattr_value ++#define udev_device_new_from_syspath \ ++ udevi->_device_new_from_syspath ++#define udev_device_unref \ ++ udevi->_device_unref ++#define udev_enumerate_add_match_property \ ++ udevi->_enumerate_add_match_property ++#define udev_enumerate_add_match_subsystem \ ++ udevi->_enumerate_add_match_subsystem ++#define udev_enumerate_get_list_entry \ ++ udevi->_enumerate_get_list_entry ++#define udev_enumerate_new \ ++ udevi->_enumerate_new ++#define udev_enumerate_scan_devices \ ++ udevi->_enumerate_scan_devices ++#define udev_enumerate_unref \ ++ udevi->_enumerate_unref ++#define udev_list_entry_get_name \ ++ udevi->_list_entry_get_name ++#define udev_list_entry_get_next \ ++ udevi->_list_entry_get_next ++#define udev_new \ ++ udevi->_new ++#define udev_unref \ ++ udevi->_unref ++#define udev_list_entry_foreach(_a, _b)\ ++ udevi_list_entry_foreach(udevi, _a, _b) ++ ++#define drmGetVersion \ ++ drmi->GetVersion ++#define drmFreeVersion \ ++ drmi->FreeVersion ++#define drmDropMaster \ ++ drmi->DropMaster ++#define drmCommandWrite \ ++ drmi->CommandWrite ++ ++#else /* HAVE_LIBUDEV */ ++ ++#include ++#include ++#include ++ ++/* Work around an incorrect define in old libdrm */ ++#undef DRM_VMW_UPDATE_LAYOUT ++#define DRM_VMW_UPDATE_LAYOUT 20 ++ ++static inline void resolutionDLClose(void) {} ++static inline int resolutionDLOpen(void) {return 0;} ++ ++#endif /* HAVE_LIBUDEV */ ++#endif /* ENABLE_RESOLUTIONKMS */ ++#endif +diff --git a/services/plugins/resolutionSet/resolutionInt.h b/services/plugins/resolutionSet/resolutionInt.h +index 55bb704..877a7bc 100644 +--- a/services/plugins/resolutionSet/resolutionInt.h ++++ b/services/plugins/resolutionSet/resolutionInt.h +@@ -74,13 +74,20 @@ typedef struct { + + extern ResolutionInfoType resolutionInfo; + ++#if defined(G_LOG_DOMAIN) ++#error Please include this file before glib.h ++#endif ++#define G_LOG_DOMAIN "resolutionSet" ++ ++#include "vmware/tools/plugin.h" ++ + /* + * Global functions + */ + + /* Functions defined by back-end. */ + Bool ResolutionBackendInit(InitHandle handle); +-InitHandle ResolutionToolkitInit(void); ++InitHandle ResolutionToolkitInit(ToolsAppCtx *ctx); + void ResolutionBackendCleanup(void); + Bool ResolutionSetResolution(uint32 width, uint32 height); + #if defined(RESOLUTION_WIN32) +@@ -90,9 +97,4 @@ void ResolutionSetSessionChange(DWORD code, DWORD sessionID); + Bool ResolutionSetTopology(unsigned int ndisplays, DisplayTopologyInfo displays[]); + Bool ResolutionSetTopologyModes(unsigned int screen, unsigned int cmd, unsigned int ndisplays, DisplayTopologyInfo displays[]); + +-#if defined(G_LOG_DOMAIN) +-#error Please include this file before glib.h +-#endif +-#define G_LOG_DOMAIN "resolutionSet" +- + #endif // ifndef _LIB_RESOLUTIONINT_H_ +diff --git a/services/plugins/resolutionSet/resolutionSet.c b/services/plugins/resolutionSet/resolutionSet.c +index 96c8349..52e0c5b 100644 +--- a/services/plugins/resolutionSet/resolutionSet.c ++++ b/services/plugins/resolutionSet/resolutionSet.c +@@ -584,9 +584,10 @@ ToolsOnLoad(ToolsAppCtx *ctx) + /* + * XXX move to some shared lib or plugin + */ +- handle = ResolutionToolkitInit(); ++ handle = ResolutionToolkitInit(ctx); + +- ResolutionInit(handle); ++ if (!ResolutionInit(handle)) ++ return NULL; + + regs[0].data = VMTools_WrapArray(rpcs, sizeof *rpcs, ARRAYSIZE(rpcs)); + regData.regs = VMTools_WrapArray(regs, sizeof *regs, ARRAYSIZE(regs)); +diff --git a/services/plugins/resolutionSet/resolutionX11.c b/services/plugins/resolutionSet/resolutionX11.c +index 3c5c120..ae42617 100644 +--- a/services/plugins/resolutionSet/resolutionX11.c ++++ b/services/plugins/resolutionSet/resolutionX11.c +@@ -45,6 +45,7 @@ + #include "strutil.h" + #include "util.h" + #include "posix.h" ++#include "resolutionCommon.h" + + #define VMWAREDRV_PATH_64 "/usr/X11R6/lib64/modules/drivers/vmware_drv.o" + #define VMWAREDRV_PATH "/usr/X11R6/lib/modules/drivers/vmware_drv.o" +@@ -105,8 +106,9 @@ ResolutionBackendInit(InitHandle handle) + resInfoX->display = handle; + + if (resInfoX->display == NULL) { +- g_warning("%s: Called with invalid X display!\n", __func__); +- return FALSE; ++ resInfo->canSetResolution = FALSE; ++ resInfo->canSetTopology = FALSE; ++ return TRUE; + } + + resInfoX->display = handle; +@@ -335,15 +337,10 @@ static Bool + ResolutionCanSet(void) + { + ResolutionInfoX11Type *resInfoX = &resolutionInfoX11; +- int fd = -1; +- off_t filePos = 0; +- Bool keepSearching = TRUE; +- Bool found = FALSE; +- char buf[sizeof VERSION_STRING + 10]; // size of VERSION_STRING plus some extra for the version number +- const char versionString[] = VERSION_STRING; +- ssize_t bytesRead; +- int32 major, minor, level; +- unsigned int tokPos; ++ int major, minor, level; ++ static const char *driverPaths[] = { ++ VMWAREDRV_PATH_64, ++ VMWAREDRV_PATH}; + + /* See if the randr X module is loaded */ + if (!XRRQueryVersion(resInfoX->display, &major, &minor) ) { +@@ -411,55 +408,9 @@ ResolutionCanSet(void) + * 6.9/7.0, we can instead just use the VMWARE_CTRL check. + */ + +- buf[sizeof buf - 1] = '\0'; +- fd = Posix_Open(VMWAREDRV_PATH_64, O_RDONLY); +- if (fd == -1) { +- fd = Posix_Open(VMWAREDRV_PATH, O_RDONLY); +- } +- if (fd != -1) { +- /* +- * One of the opens succeeded, so start searching thru the file. +- */ +- while (keepSearching) { +- bytesRead = read(fd, buf, sizeof buf - 1); +- if (bytesRead == -1 || bytesRead < sizeof buf -1 ) { +- keepSearching = FALSE; +- } else { +- if (Str_Strncmp(versionString, buf, sizeof versionString - 1) == 0) { +- keepSearching = FALSE; +- found = TRUE; +- } +- } +- filePos = lseek(fd, filePos+1, SEEK_SET); +- if (filePos == -1) { +- keepSearching = FALSE; +- } +- } +- close(fd); +- if (found) { +- /* +- * We NUL-terminated buf earlier, but Coverity really wants it to +- * be NUL-terminated after the call to read (because +- * read doesn't NUL-terminate). So we'll do it again. +- */ +- buf[sizeof buf - 1] = '\0'; +- +- /* +- * Try and parse the major, minor and level versions +- */ +- tokPos = sizeof versionString - 1; +- if (!StrUtil_GetNextIntToken(&major, &tokPos, buf, ".- ")) { +- return FALSE; +- } +- if (!StrUtil_GetNextIntToken(&minor, &tokPos, buf, ".- ")) { +- return FALSE; +- } +- if (!StrUtil_GetNextIntToken(&level, &tokPos, buf, ".- ")) { +- return FALSE; +- } +- +- return ((major > 10) || (major == 10 && minor >= 11)); +- } ++ if (!resolutionXorgDriverVersion(2, driverPaths, VERSION_STRING, ++ &major, &minor, &level)) { ++ return ((major > 10) || (major == 10 && minor >= 11)); + } + return FALSE; + } +@@ -633,12 +584,20 @@ ResolutionX11ErrorHandler(Display *d, // IN: Pointer to display connection + */ + + InitHandle +-ResolutionToolkitInit(void) ++ResolutionToolkitInit(ToolsAppCtx *ctx) // IN: For config database access + { + int argc = 1; + char *argv[] = {"", NULL}; + GtkWidget *wnd; + Display *display; ++ int fd; ++ ++ fd = resolutionCheckForKMS(ctx); ++ if (fd >= 0) { ++ resolutionDRMClose(fd); ++ g_message("%s: Backing off for resolutionKMS.\n", __func__); ++ return (InitHandle) 0; ++ } + + XSetErrorHandler(ResolutionX11ErrorHandler); + gtk_init(&argc, (char ***) &argv); +@@ -648,5 +607,9 @@ ResolutionToolkitInit(void) + #else + display = GDK_WINDOW_XDISPLAY(gtk_widget_get_window(wnd)); + #endif ++ ++ if (!display) ++ g_error("%s: Invalid display detected.\n", __func__); ++ + return (InitHandle) display; + }