aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--MAINTAINERS6
-rw-r--r--Makefile4
-rw-r--r--Makefile.objs14
-rwxr-xr-xconfigure86
-rw-r--r--docs/libcacard.txt483
-rw-r--r--docs/win32-qemu-event.promela98
-rw-r--r--hw/arm/virt-acpi-build.c56
-rw-r--r--hw/arm/virt.c124
-rw-r--r--hw/intc/Makefile.objs2
-rw-r--r--hw/intc/arm_gic_kvm.c98
-rw-r--r--hw/intc/arm_gicv3_common.c140
-rw-r--r--hw/intc/arm_gicv3_kvm.c149
-rw-r--r--hw/intc/vgic_common.h35
-rw-r--r--hw/usb/Makefile.objs5
-rw-r--r--hw/usb/ccid-card-passthru.c2
-rw-r--r--include/hw/acpi/acpi-defs.h9
-rw-r--r--include/hw/arm/virt-acpi-build.h1
-rw-r--r--include/hw/arm/virt.h4
-rw-r--r--include/hw/intc/arm_gicv3_common.h68
-rw-r--r--include/qemu/osdep.h4
-rw-r--r--include/qemu/thread-win32.h1
-rw-r--r--include/sysemu/kvm.h26
-rw-r--r--include/sysemu/os-win32.h2
-rw-r--r--include/ui/gtk.h4
-rw-r--r--kvm-all.c34
-rw-r--r--libcacard/Makefile45
-rw-r--r--libcacard/cac.c414
-rw-r--r--libcacard/cac.h31
-rw-r--r--libcacard/card_7816.c757
-rw-r--r--libcacard/card_7816.h62
-rw-r--r--libcacard/card_7816t.h165
-rw-r--r--libcacard/event.c103
-rw-r--r--libcacard/eventt.h29
-rw-r--r--libcacard/libcacard.pc.in13
-rw-r--r--libcacard/libcacard.syms77
-rw-r--r--libcacard/link_test.c22
-rw-r--r--libcacard/vcard.c325
-rw-r--r--libcacard/vcard.h86
-rw-r--r--libcacard/vcard_emul.h66
-rw-r--r--libcacard/vcard_emul_nss.c1274
-rw-r--r--libcacard/vcard_emul_type.c57
-rw-r--r--libcacard/vcard_emul_type.h32
-rw-r--r--libcacard/vcardt.c40
-rw-r--r--libcacard/vcardt.h59
-rw-r--r--libcacard/vcardt_internal.h6
-rw-r--r--libcacard/vevent.h27
-rw-r--r--libcacard/vreader.c578
-rw-r--r--libcacard/vreader.h55
-rw-r--r--libcacard/vreadert.h24
-rw-r--r--libcacard/vscard_common.h178
-rw-r--r--libcacard/vscclient.c785
-rw-r--r--qemu.nsi3
-rw-r--r--slirp/tcp_input.c8
-rw-r--r--target-arm/kvm.c19
-rw-r--r--target-arm/kvm_arm.h19
-rw-r--r--target-arm/machine.c18
-rw-r--r--ui/gtk.c9
-rw-r--r--util/oslib-win32.c2
-rw-r--r--util/qemu-thread-win32.c66
60 files changed, 929 insertions, 5981 deletions
diff --git a/.gitignore b/.gitignore
index fdd721dba1..75bceb9975 100644
--- a/.gitignore
+++ b/.gitignore
@@ -19,7 +19,6 @@
/trace/generated-ust.c
/ui/shader/texture-blit-frag.h
/ui/shader/texture-blit-vert.h
-/libcacard/trace/generated-tracers.c
*-timestamp
/*-softmmu
/*-darwin-user
diff --git a/MAINTAINERS b/MAINTAINERS
index b2e5fbd8e5..7aff1627b6 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -266,10 +266,10 @@ F: *win32*
ARM Machines
------------
Allwinner-a10
-M: Li Guang <lig.fnst@cn.fujitsu.com>
+M: Beniamino Galvani <b.galvani@gmail.com>
S: Maintained
-F: hw/*/allwinner-a10*
-F: include/hw/*/allwinner-a10*
+F: hw/*/allwinner*
+F: include/hw/*/allwinner*
F: hw/arm/cubieboard.c
Exynos
diff --git a/Makefile b/Makefile
index 8ec9b69b2f..68e2e1b3fe 100644
--- a/Makefile
+++ b/Makefile
@@ -163,9 +163,6 @@ dummy := $(call unnest-vars,, \
ifneq ($(wildcard config-host.mak),)
include $(SRC_PATH)/tests/Makefile
endif
-ifeq ($(CONFIG_SMARTCARD_NSS),y)
-include $(SRC_PATH)/libcacard/Makefile
-endif
all: $(DOCS) $(TOOLS) $(HELPERS-y) recurse-all modules
@@ -626,6 +623,7 @@ endif # SIGNCODE
$(if $(DLL_PATH),-DDLLDIR="$(DLL_PATH)") \
-DSRCDIR="$(SRC_PATH)" \
-DOUTFILE="$(INSTALLER)" \
+ -DDISPLAYVERSION="$(VERSION)" \
$(SRC_PATH)/qemu.nsi
rm -r ${INSTDIR}
ifdef SIGNCODE
diff --git a/Makefile.objs b/Makefile.objs
index ce87778828..bc43e5c1dd 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -33,18 +33,6 @@ crypto-aes-obj-y = crypto/
qom-obj-y = qom/
######################################################################
-# smartcard
-
-libcacard-y += libcacard/cac.o libcacard/event.o
-libcacard-y += libcacard/vcard.o libcacard/vreader.o
-libcacard-y += libcacard/vcard_emul_nss.o
-libcacard-y += libcacard/vcard_emul_type.o
-libcacard-y += libcacard/card_7816.o
-libcacard-y += libcacard/vcardt.o
-libcacard/vcard_emul_nss.o-cflags := $(NSS_CFLAGS)
-libcacard/vcard_emul_nss.o-libs := $(NSS_LIBS)
-
-######################################################################
# Target independent part of system emulation. The long term path is to
# suppress *all* target specific code in case of system emulation, i.e. a
# single QEMU executable should support all CPUs and machines.
@@ -85,8 +73,6 @@ common-obj-y += backends/
common-obj-$(CONFIG_SECCOMP) += qemu-seccomp.o
-common-obj-$(CONFIG_SMARTCARD_NSS) += $(libcacard-y)
-
common-obj-$(CONFIG_FDT) += device_tree.o
######################################################################
diff --git a/configure b/configure
index 52f5b79fe6..f14454e691 100755
--- a/configure
+++ b/configure
@@ -302,7 +302,7 @@ trace_backends="nop"
trace_file="trace"
spice=""
rbd=""
-smartcard_nss=""
+smartcard=""
libusb=""
usb_redir=""
opengl=""
@@ -1039,9 +1039,9 @@ for opt do
;;
--enable-xfsctl) xfs="yes"
;;
- --disable-smartcard-nss) smartcard_nss="no"
+ --disable-smartcard) smartcard="no"
;;
- --enable-smartcard-nss) smartcard_nss="yes"
+ --enable-smartcard) smartcard="yes"
;;
--disable-libusb) libusb="no"
;;
@@ -1354,7 +1354,7 @@ disabled with --disable-FEATURE, default is enabled if available:
rbd rados block device (rbd)
libiscsi iscsi support
libnfs nfs support
- smartcard-nss smartcard nss support
+ smartcard smartcard support (libcacard)
libusb libusb (for usb passthrough)
usb-redir usb network redirection support
lzo support of lzo compression library
@@ -1737,6 +1737,37 @@ else
fi
##########################################
+# MinGW / Mingw-w64 localtime_r/gmtime_r check
+
+if test "$mingw32" = "yes"; then
+ # Some versions of MinGW / Mingw-w64 lack localtime_r
+ # and gmtime_r entirely.
+ #
+ # Some versions of Mingw-w64 define a macro for
+ # localtime_r/gmtime_r.
+ #
+ # Some versions of Mingw-w64 will define functions
+ # for localtime_r/gmtime_r, but only if you have
+ # _POSIX_THREAD_SAFE_FUNCTIONS defined. For fun
+ # though, unistd.h and pthread.h both define
+ # that for you.
+ #
+ # So this #undef localtime_r and #include <unistd.h>
+ # are not in fact redundant.
+cat > $TMPC << EOF
+#include <unistd.h>
+#include <time.h>
+#undef localtime_r
+int main(void) { localtime_r(NULL, NULL); return 0; }
+EOF
+ if compile_prog "" "" ; then
+ localtime_r="yes"
+ else
+ localtime_r="no"
+ fi
+fi
+
+##########################################
# pkg-config probe
if ! has "$pkg_config_exe"; then
@@ -3810,34 +3841,20 @@ EOF
fi
fi
-# check for libcacard for smartcard support
+# check for smartcard support
smartcard_cflags=""
-# TODO - what's the minimal nss version we support?
-if test "$smartcard_nss" != "no"; then
- cat > $TMPC << EOF
-#include <pk11pub.h>
-int main(void) { PK11_FreeSlot(0); return 0; }
-EOF
- # FIXME: do not include $glib_* in here
- nss_libs="$($pkg_config --libs nss 2>/dev/null) $glib_libs"
- nss_cflags="$($pkg_config --cflags nss 2>/dev/null) $glib_cflags"
- test_cflags="$nss_cflags"
- # The header files in nss < 3.13.3 have a bug which causes them to
- # emit a warning. If we're going to compile QEMU with -Werror, then
- # test that the headers don't have this bug. Otherwise we would pass
- # the configure test but fail to compile QEMU later.
- if test "$werror" = "yes"; then
- test_cflags="-Werror $test_cflags"
- fi
- if test -n "$libtool" &&
- $pkg_config --atleast-version=3.12.8 nss && \
- compile_prog "$test_cflags" "$nss_libs"; then
- smartcard_nss="yes"
+if test "$smartcard" != "no"; then
+ if $pkg_config libcacard; then
+ libcacard_cflags=$($pkg_config --cflags libcacard)
+ libcacard_libs=$($pkg_config --libs libcacard)
+ QEMU_CFLAGS="$QEMU_CFLAGS $libcacard_cflags"
+ libs_softmmu="$libs_softmmu $libcacard_libs"
+ smartcard="yes"
else
- if test "$smartcard_nss" = "yes"; then
- feature_not_found "nss" "Install nss devel >= 3.12.8"
+ if test "$smartcard" = "yes"; then
+ feature_not_found "smartcard" "Install libcacard devel"
fi
- smartcard_nss="no"
+ smartcard="no"
fi
fi
@@ -4618,7 +4635,7 @@ echo "spice support $spice"
fi
echo "rbd support $rbd"
echo "xfsctl support $xfs"
-echo "nss used $smartcard_nss"
+echo "smartcard support $smartcard"
echo "libusb $libusb"
echo "usb net redir $usb_redir"
echo "OpenGL support $opengl"
@@ -4995,10 +5012,8 @@ if test "$spice" = "yes" ; then
echo "CONFIG_SPICE=y" >> $config_host_mak
fi
-if test "$smartcard_nss" = "yes" ; then
- echo "CONFIG_SMARTCARD_NSS=y" >> $config_host_mak
- echo "NSS_LIBS=$nss_libs" >> $config_host_mak
- echo "NSS_CFLAGS=$nss_cflags" >> $config_host_mak
+if test "$smartcard" = "yes" ; then
+ echo "CONFIG_SMARTCARD=y" >> $config_host_mak
fi
if test "$libusb" = "yes" ; then
@@ -5050,6 +5065,9 @@ fi
if test "$zero_malloc" = "yes" ; then
echo "CONFIG_ZERO_MALLOC=y" >> $config_host_mak
fi
+if test "$localtime_r" = "yes" ; then
+ echo "CONFIG_LOCALTIME_R=y" >> $config_host_mak
+fi
if test "$qom_cast_debug" = "yes" ; then
echo "CONFIG_QOM_CAST_DEBUG=y" >> $config_host_mak
fi
diff --git a/docs/libcacard.txt b/docs/libcacard.txt
deleted file mode 100644
index 499cf7d79c..0000000000
--- a/docs/libcacard.txt
+++ /dev/null
@@ -1,483 +0,0 @@
-This file documents the CAC (Common Access Card) library in the libcacard
-subdirectory.
-
-Virtual Smart Card Emulator
-
-This emulator is designed to provide emulation of actual smart cards to a
-virtual card reader running in a guest virtual machine. The emulated smart
-cards can be representations of real smart cards, where the necessary functions
-such as signing, card removal/insertion, etc. are mapped to real, physical
-cards which are shared with the client machine the emulator is running on, or
-the cards could be pure software constructs.
-
-The emulator is structured to allow multiple replaceable or additional pieces,
-so it can be easily modified for future requirements. The primary envisioned
-modifications are:
-
-1) The socket connection to the virtual card reader (presumably a CCID reader,
-but other ISO-7816 compatible readers could be used). The code that handles
-this is in vscclient.c.
-
-2) The virtual card low level emulation. This is currently supplied by using
-NSS. This emulation could be replaced by implementations based on other
-security libraries, including but not limitted to openssl+pkcs#11 library,
-raw pkcs#11, Microsoft CAPI, direct opensc calls, etc. The code that handles
-this is in vcard_emul_nss.c.
-
-3) Emulation for new types of cards. The current implementation emulates the
-original DoD CAC standard with separate pki containers. This emulator lives in
-cac.c. More than one card type emulator could be included. Other cards could
-be emulated as well, including PIV, newer versions of CAC, PKCS #15, etc.
-
---------------------
-Replacing the Socket Based Virtual Reader Interface.
-
-The current implementation contains a replaceable module vscclient.c. The
-current vscclient.c implements a sockets interface to the virtual ccid reader
-on the guest. CCID commands that are pertinent to emulation are passed
-across the socket, and their responses are passed back along that same socket.
-The protocol that vscclient uses is defined in vscard_common.h and connects
-to a qemu ccid usb device. Since this socket runs as a client, vscclient.c
-implements a program with a main entry. It also handles argument parsing for
-the emulator.
-
-An application that wants to use the virtual reader can replace vscclient.c
-with its own implementation that connects to its own CCID reader. The calls
-that the CCID reader can call are:
-
- VReaderList * vreader_get_reader_list();
-
- This function returns a list of virtual readers. These readers may map to
- physical devices, or simulated devices depending on vcard the back end. Each
- reader in the list should represent a reader to the virtual machine. Virtual
- USB address mapping is left to the CCID reader front end. This call can be
- made any time to get an updated list. The returned list is a copy of the
- internal list that can be referenced by the caller without locking. This copy
- must be freed by the caller with vreader_list_delete when it is no longer
- needed.
-
- VReaderListEntry *vreader_list_get_first(VReaderList *);
-
- This function gets the first entry on the reader list. Along with
- vreader_list_get_next(), vreader_list_get_first() can be used to walk the
- reader list returned from vreader_get_reader_list(). VReaderListEntries are
- part of the list themselves and do not need to be freed separately from the
- list. If there are no entries on the list, it will return NULL.
-
- VReaderListEntry *vreader_list_get_next(VReaderListEntry *);
-
- This function gets the next entry in the list. If there are no more entries
- it will return NULL.
-
- VReader * vreader_list_get_reader(VReaderListEntry *)
-
- This function returns the reader stored in the reader List entry. Caller gets
- a new reference to a reader. The caller must free its reference when it is
- finished with vreader_free().
-
- void vreader_free(VReader *reader);
-
- This function frees a reference to a reader. Readers are reference counted
- and are automatically deleted when the last reference is freed.
-
- void vreader_list_delete(VReaderList *list);
-
- This function frees the list, all the elements on the list, and all the
- reader references held by the list.
-
- VReaderStatus vreader_power_on(VReader *reader, char *atr, int *len);
-
- This function simulates a card power on. A virtual card does not care about
- the actual voltage and other physical parameters, but it does care that the
- card is actually on or off. Cycling the card causes the card to reset. If
- the caller provides enough space, vreader_power_on will return the ATR of
- the virtual card. The amount of space provided in atr should be indicated
- in *len. The function modifies *len to be the actual length of of the
- returned ATR.
-
- VReaderStatus vreader_power_off(VReader *reader);
-
- This function simulates a power off of a virtual card.
-
- VReaderStatus vreader_xfer_bytes(VReader *reader, unsigne char *send_buf,
- int send_buf_len,
- unsigned char *receive_buf,
- int receive_buf_len);
-
- This function sends a raw apdu to a card and returns the card's response.
- The CCID front end should return the response back. Most of the emulation
- is driven from these APDUs.
-
- VReaderStatus vreader_card_is_present(VReader *reader);
-
- This function returns whether or not the reader has a card inserted. The
- vreader_power_on, vreader_power_off, and vreader_xfer_bytes will return
- VREADER_NO_CARD.
-
- const char *vreader_get_name(VReader *reader);
-
- This function returns the name of the reader. The name comes from the card
- emulator level and is usually related to the name of the physical reader.
-
- VReaderID vreader_get_id(VReader *reader);
-
- This function returns the id of a reader. All readers start out with an id
- of -1. The application can set the id with vreader_set_id.
-
- VReaderStatus vreader_get_id(VReader *reader, VReaderID id);
-
- This function sets the reader id. The application is responsible for making
- sure that the id is unique for all readers it is actively using.
-
- VReader *vreader_find_reader_by_id(VReaderID id);
-
- This function returns the reader which matches the id. If two readers match,
- only one is returned. The function returns NULL if the id is -1.
-
- Event *vevent_wait_next_vevent();
-
- This function blocks waiting for reader and card insertion events. There
- will be one event for each card insertion, each card removal, each reader
- insertion and each reader removal. At start up, events are created for all
- the initial readers found, as well as all the cards that are inserted.
-
- Event *vevent_get_next_vevent();
-
- This function returns a pending event if it exists, otherwise it returns
- NULL. It does not block.
-
-----------------
-Card Type Emulator: Adding a New Virtual Card Type
-
-The ISO 7816 card spec describes 2 types of cards:
- 1) File system cards, where the smartcard is managed by reading and writing
-data to files in a file system. There is currently only boiler plate
-implemented for file system cards.
- 2) VM cards, where the card has loadable applets which perform the card
-functions. The current implementation supports VM cards.
-
-In the case of VM cards, the difference between various types of cards is
-really what applets have been installed in that card. This structure is
-mirrored in card type emulators. The 7816 emulator already handles the basic
-ISO 7186 commands. Card type emulators simply need to add the virtual applets
-which emulate the real card applets. Card type emulators have exactly one
-public entry point:
-
- VCARDStatus xxx_card_init(VCard *card, const char *flags,
- const unsigned char *cert[],
- int cert_len[],
- VCardKey *key[],
- int cert_count);
-
- The parameters for this are:
- card - the virtual card structure which will represent this card.
- flags - option flags that may be specific to this card type.
- cert - array of binary certificates.
- cert_len - array of lengths of each of the certificates specified in cert.
- key - array of opaque key structures representing the private keys on
- the card.
- cert_count - number of entries in cert, cert_len, and key arrays.
-
- Any cert, cert_len, or key with the same index are matching sets. That is
- cert[0] is cert_len[0] long and has the corresponding private key of key[0].
-
-The card type emulator is expected to own the VCardKeys, but it should copy
-any raw cert data it wants to save. It can create new applets and add them to
-the card using the following functions:
-
- VCardApplet *vcard_new_applet(VCardProcessAPDU apdu_func,
- VCardResetApplet reset_func,
- const unsigned char *aid,
- int aid_len);
-
- This function creates a new applet. Applet structures store the following
- information:
- 1) the AID of the applet (set by aid and aid_len).
- 2) a function to handle APDUs for this applet. (set by apdu_func, more on
- this below).
- 3) a function to reset the applet state when the applet is selected.
- (set by reset_func, more on this below).
- 3) applet private data, a data pointer used by the card type emulator to
- store any data or state it needs to complete requests. (set by a
- separate call).
- 4) applet private data free, a function used to free the applet private
- data when the applet itself is destroyed.
- The created applet can be added to the card with vcard_add_applet below.
-
- void vcard_set_applet_private(VCardApplet *applet,
- VCardAppletPrivate *private,
- VCardAppletPrivateFree private_free);
- This function sets the private data and the corresponding free function.
- VCardAppletPrivate is an opaque data structure to the rest of the emulator.
- The card type emulator can define it any way it wants by defining
- struct VCardAppletPrivateStruct {};. If there is already a private data
- structure on the applet, the old one is freed before the new one is set up.
- passing two NULL clear any existing private data.
-
- VCardStatus vcard_add_applet(VCard *card, VCardApplet *applet);
-
- Add an applet onto the list of applets attached to the card. Once an applet
- has been added, it can be selected by its AID, and then commands will be
- routed to it VCardProcessAPDU function. This function adopts the applet that
- is passed into it. Note: 2 applets with the same AID should not be added to
- the same card. It is permissible to add more than one applet. Multiple applets
- may have the same VCardPRocessAPDU entry point.
-
-The certs and keys should be attached to private data associated with one or
-more appropriate applets for that card. Control will come to the card type
-emulators once one of its applets are selected through the VCardProcessAPDU
-function it specified when it created the applet.
-
-The signature of VCardResetApplet is:
- VCardStatus (*VCardResetApplet) (VCard *card, int channel);
- This function will reset the any internal applet state that needs to be
- cleared after a select applet call. It should return VCARD_DONE;
-
-The signature of VCardProcessAPDU is:
- VCardStatus (*VCardProcessAPDU)(VCard *card, VCardAPDU *apdu,
- VCardResponse **response);
- This function examines the APDU and determines whether it should process
- the apdu directly, reject the apdu as invalid, or pass the apdu on to
- the basic 7816 emulator for processing.
- If the 7816 emulator should process the apdu, then the VCardProcessAPDU
- should return VCARD_NEXT.
- If there is an error, then VCardProcessAPDU should return an error
- response using vcard_make_response and the appropriate 7816 error code
- (see card_7816t.h) or vcard_make_response with a card type specific error
- code. It should then return VCARD_DONE.
- If the apdu can be processed correctly, VCardProcessAPDU should do so,
- set the response value appropriately for that APDU, and return VCARD_DONE.
- VCardProcessAPDU should always set the response if it returns VCARD_DONE.
- It should always either return VCARD_DONE or VCARD_NEXT.
-
-Parsing the APDU --
-
-Prior to processing calling the card type emulator's VCardProcessAPDU function, the emulator has already decoded the APDU header and set several fields:
-
- apdu->a_data - The raw apdu data bytes.
- apdu->a_len - The len of the raw apdu data.
- apdu->a_body - The start of any post header parameter data.
- apdu->a_Lc - The parameter length value.
- apdu->a_Le - The expected length of any returned data.
- apdu->a_cla - The raw apdu class.
- apdu->a_channel - The channel (decoded from the class).
- apdu->a_secure_messaging_type - The decoded secure messaging type
- (from class).
- apdu->a_type - The decode class type.
- apdu->a_gen_type - the generic class type (7816, PROPRIETARY, RFU, PTS).
- apdu->a_ins - The instruction byte.
- apdu->a_p1 - Parameter 1.
- apdu->a_p2 - Parameter 2.
-
-Creating a Response --
-
-The expected result of any APDU call is a response. The card type emulator must
-set *response with an appropriate VCardResponse value if it returns VCARD_DONE.
-Responses could be as simple as returning a 2 byte status word response, to as
-complex as returning a block of data along with a 2 byte response. Which is
-returned will depend on the semantics of the APDU. The following functions will
-create card responses.
-
- VCardResponse *vcard_make_response(VCard7816Status status);
-
- This is the most basic function to get a response. This function will
- return a response the consists solely one 2 byte status code. If that status
- code is defined in card_7816t.h, then this function is guaranteed to
- return a response with that status. If a cart type specific status code
- is passed and vcard_make_response fails to allocate the appropriate memory
- for that response, then vcard_make_response will return a VCardResponse
- of VCARD7816_STATUS_EXC_ERROR_MEMORY. In any case, this function is
- guaranteed to return a valid VCardResponse.
-
- VCardResponse *vcard_response_new(unsigned char *buf, int len,
- VCard7816Status status);
-
- This function is similar to vcard_make_response except it includes some
- returned data with the response. It could also fail to allocate enough
- memory, in which case it will return NULL.
-
- VCardResponse *vcard_response_new_status_bytes(unsigned char sw1,
- unsigned char sw2);
-
- Sometimes in 7816 the response bytes are treated as two separate bytes with
- split meanings. This function allows you to create a response based on
- two separate bytes. This function could fail, in which case it will return
- NULL.
-
- VCardResponse *vcard_response_new_bytes(unsigned char *buf, int len,
- unsigned char sw1,
- unsigned char sw2);
-
- This function is the same as vcard_response_new except you may specify
- the status as two separate bytes like vcard_response_new_status_bytes.
-
-
-Implementing functionality ---
-
-The following helper functions access information about the current card
-and applet.
-
- VCARDAppletPrivate *vcard_get_current_applet_private(VCard *card,
- int channel);
-
- This function returns any private data set by the card type emulator on
- the currently selected applet. The card type emulator keeps track of the
- current applet state in this data structure. Any certs and keys associated
- with a particular applet is also stored here.
-
- int vcard_emul_get_login_count(VCard *card);
-
- This function returns the number of remaining login attempts for this
- card. If the card emulator does not know, or the card does not have a
- way of giving this information, this function returns -1.
-
-
- VCard7816Status vcard_emul_login(VCard *card, unsigned char *pin,
- int pin_len);
-
- This function logs into the card and returns the standard 7816 status
- word depending on the success or failure of the call.
-
- void vcard_emul_delete_key(VCardKey *key);
-
- This function frees the VCardKey passed in to xxxx_card_init. The card
- type emulator is responsible for freeing this key when it no longer needs
- it.
-
- VCard7816Status vcard_emul_rsa_op(VCard *card, VCardKey *key,
- unsigned char *buffer,
- int buffer_size);
-
- This function does a raw rsa op on the buffer with the given key.
-
-The sample card type emulator is found in cac.c. It implements the cac specific
-applets. Only those applets needed by the coolkey pkcs#11 driver on the guest
-have been implemented. To support the full range CAC middleware, a complete CAC
-card according to the CAC specs should be implemented here.
-
-------------------------------
-Virtual Card Emulator
-
-This code accesses both real smart cards and simulated smart cards through
-services provided on the client. The current implementation uses NSS, which
-already knows how to talk to various PKCS #11 modules on the client, and is
-portable to most operating systems. A particular emulator can have only one
-virtual card implementation at a time.
-
-The virtual card emulator consists of a series of virtual card services. In
-addition to the services describe above (services starting with
-vcard_emul_xxxx), the virtual card emulator also provides the following
-functions:
-
- VCardEmulError vcard_emul_init(cont VCardEmulOptions *options);
-
- The options structure is built by another function in the virtual card
- interface where a string of virtual card emulator specific strings are
- mapped to the options. The actual structure is defined by the virtual card
- emulator and is used to determine the configuration of soft cards, or to
- determine which physical cards to present to the guest.
-
- The vcard_emul_init function will build up sets of readers, create any
- threads that are needed to watch for changes in the reader state. If readers
- have cards present in them, they are also initialized.
-
- Readers are created with the function.
-
- VReader *vreader_new(VReaderEmul *reader_emul,
- VReaderEmulFree reader_emul_free);
-
- The freeFunc is used to free the VReaderEmul * when the reader is
- destroyed. The VReaderEmul structure is an opaque structure to the
- rest of the code, but defined by the virtual card emulator, which can
- use it to store any reader specific state.
-
- Once the reader has been created, it can be added to the front end with the
- call:
-
- VReaderStatus vreader_add_reader(VReader *reader);
-
- This function will automatically generate the appropriate new reader
- events and add the reader to the list.
-
- To create a new card, the virtual card emulator will call a similar
- function.
-
- VCard *vcard_new(VCardEmul *card_emul,
- VCardEmulFree card_emul_free);
-
- Like vreader_new, this function takes a virtual card emulator specific
- structure which it uses to keep track of the card state.
-
- Once the card is created, it is attached to a card type emulator with the
- following function:
-
- VCardStatus vcard_init(VCard *vcard, VCardEmulType type,
- const char *flags,
- unsigned char *const *certs,
- int *cert_len,
- VCardKey *key[],
- int cert_count);
-
- The vcard is the value returned from vcard_new. The type is the
- card type emulator that this card should presented to the guest as.
- The flags are card type emulator specific options. The certs,
- cert_len, and keys are all arrays of length cert_count. These are
- the same of the parameters xxxx_card_init() accepts.
-
- Finally the card is associated with its reader by the call:
-
- VReaderStatus vreader_insert_card(VReader *vreader, VCard *vcard);
-
- This function, like vreader_add_reader, will take care of any event
- notification for the card insert.
-
-
- VCardEmulError vcard_emul_force_card_remove(VReader *vreader);
-
- Force a card that is present to appear to be removed to the guest, even if
- that card is a physical card and is present.
-
-
- VCardEmulError vcard_emul_force_card_insert(VReader *reader);
-
- Force a card that has been removed by vcard_emul_force_card_remove to be
- reinserted from the point of view of the guest. This will only work if the
- card is physically present (which is always true fro a soft card).
-
- void vcard_emul_get_atr(Vcard *card, unsigned char *atr, int *atr_len);
-
- Return the virtual ATR for the card. By convention this should be the value
- VCARD_ATR_PREFIX(size) followed by several ascii bytes related to this
- particular emulator. For instance the NSS emulator returns
- {VCARD_ATR_PREFIX(3), 'N', 'S', 'S' }. Do ot return more data then *atr_len;
-
- void vcard_emul_reset(VCard *card, VCardPower power)
-
- Set the state of 'card' to the current power level and reset its internal
- state (logout, etc).
-
--------------------------------------------------------
-List of files and their function:
-README - This file
-card_7816.c - emulate basic 7816 functionality. Parse APDUs.
-card_7816.h - apdu and response services definitions.
-card_7816t.h - 7816 specific structures, types and definitions.
-event.c - event handling code.
-event.h - event handling services definitions.
-eventt.h - event handling structures and types
-vcard.c - handle common virtual card services like creation, destruction, and
- applet management.
-vcard.h - common virtual card services function definitions.
-vcardt.h - comon virtual card types
-vreader.c - common virtual reader services.
-vreader.h - common virtual reader services definitions.
-vreadert.h - comon virtual reader types.
-vcard_emul_type.c - manage the card type emulators.
-vcard_emul_type.h - definitions for card type emulators.
-cac.c - card type emulator for CAC cards
-vcard_emul.h - virtual card emulator service definitions.
-vcard_emul_nss.c - virtual card emulator implementation for nss.
-vscclient.c - socket connection to guest qemu usb driver.
-vscard_common.h - common header with the guest qemu usb driver.
-mutex.h - header file for machine independent mutexes.
-link_test.c - static test to make sure all the symbols are properly defined.
diff --git a/docs/win32-qemu-event.promela b/docs/win32-qemu-event.promela
new file mode 100644
index 0000000000..c446a71555
--- /dev/null
+++ b/docs/win32-qemu-event.promela
@@ -0,0 +1,98 @@
+/*
+ * This model describes the implementation of QemuEvent in
+ * util/qemu-thread-win32.c.
+ *
+ * Author: Paolo Bonzini <pbonzini@redhat.com>
+ *
+ * This file is in the public domain. If you really want a license,
+ * the WTFPL will do.
+ *
+ * To verify it:
+ * spin -a docs/event.promela
+ * gcc -O2 pan.c -DSAFETY
+ * ./a.out
+ */
+
+bool event;
+int value;
+
+/* Primitives for a Win32 event */
+#define RAW_RESET event = false
+#define RAW_SET event = true
+#define RAW_WAIT do :: event -> break; od
+
+#if 0
+/* Basic sanity checking: test the Win32 event primitives */
+#define RESET RAW_RESET
+#define SET RAW_SET
+#define WAIT RAW_WAIT
+#else
+/* Full model: layer a userspace-only fast path on top of the RAW_*
+ * primitives. SET/RESET/WAIT have exactly the same semantics as
+ * RAW_SET/RAW_RESET/RAW_WAIT, but try to avoid invoking them.
+ */
+#define EV_SET 0
+#define EV_FREE 1
+#define EV_BUSY -1
+
+int state = EV_FREE;
+
+int xchg_result;
+#define SET if :: state != EV_SET -> \
+ atomic { /* xchg_result=xchg(state, EV_SET) */ \
+ xchg_result = state; \
+ state = EV_SET; \
+ } \
+ if :: xchg_result == EV_BUSY -> RAW_SET; \
+ :: else -> skip; \
+ fi; \
+ :: else -> skip; \
+ fi
+
+#define RESET if :: state == EV_SET -> atomic { state = state | EV_FREE; } \
+ :: else -> skip; \
+ fi
+
+int tmp1, tmp2;
+#define WAIT tmp1 = state; \
+ if :: tmp1 != EV_SET -> \
+ if :: tmp1 == EV_FREE -> \
+ RAW_RESET; \
+ atomic { /* tmp2=cas(state, EV_FREE, EV_BUSY) */ \
+ tmp2 = state; \
+ if :: tmp2 == EV_FREE -> state = EV_BUSY; \
+ :: else -> skip; \
+ fi; \
+ } \
+ if :: tmp2 == EV_SET -> tmp1 = EV_SET; \
+ :: else -> tmp1 = EV_BUSY; \
+ fi; \
+ :: else -> skip; \
+ fi; \
+ assert(tmp1 != EV_FREE); \
+ if :: tmp1 == EV_BUSY -> RAW_WAIT; \
+ :: else -> skip; \
+ fi; \
+ :: else -> skip; \
+ fi
+#endif
+
+active proctype waiter()
+{
+ if
+ :: !value ->
+ RESET;
+ if
+ :: !value -> WAIT;
+ :: else -> skip;
+ fi;
+ :: else -> skip;
+ fi;
+ assert(value);
+}
+
+active proctype notifier()
+{
+ value = true;
+ SET;
+}
diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
index 9088248c3a..1aaff1f662 100644
--- a/hw/arm/virt-acpi-build.c
+++ b/hw/arm/virt-acpi-build.c
@@ -114,7 +114,7 @@ static void acpi_dsdt_add_flash(Aml *scope, const MemMapEntry *flash_memmap)
{
Aml *dev, *crs;
hwaddr base = flash_memmap->base;
- hwaddr size = flash_memmap->size;
+ hwaddr size = flash_memmap->size / 2;
dev = aml_device("FLS0");
aml_append(dev, aml_name_decl("_HID", aml_string("LNRO0015")));
@@ -443,33 +443,43 @@ build_madt(GArray *table_data, GArray *linker, VirtGuestInfo *guest_info,
madt = acpi_data_push(table_data, sizeof *madt);
- for (i = 0; i < guest_info->smp_cpus; i++) {
- AcpiMadtGenericInterrupt *gicc = acpi_data_push(table_data,
- sizeof *gicc);
- gicc->type = ACPI_APIC_GENERIC_INTERRUPT;
- gicc->length = sizeof(*gicc);
- gicc->base_address = memmap[VIRT_GIC_CPU].base;
- gicc->cpu_interface_number = i;
- gicc->arm_mpidr = i;
- gicc->uid = i;
- if (test_bit(i, cpuinfo->found_cpus)) {
- gicc->flags = cpu_to_le32(ACPI_GICC_ENABLED);
- }
- }
-
gicd = acpi_data_push(table_data, sizeof *gicd);
gicd->type = ACPI_APIC_GENERIC_DISTRIBUTOR;
gicd->length = sizeof(*gicd);
gicd->base_address = memmap[VIRT_GIC_DIST].base;
- gic_msi = acpi_data_push(table_data, sizeof *gic_msi);
- gic_msi->type = ACPI_APIC_GENERIC_MSI_FRAME;
- gic_msi->length = sizeof(*gic_msi);
- gic_msi->gic_msi_frame_id = 0;
- gic_msi->base_address = cpu_to_le64(memmap[VIRT_GIC_V2M].base);
- gic_msi->flags = cpu_to_le32(1);
- gic_msi->spi_count = cpu_to_le16(NUM_GICV2M_SPIS);
- gic_msi->spi_base = cpu_to_le16(irqmap[VIRT_GIC_V2M] + ARM_SPI_BASE);
+ if (guest_info->gic_version == 3) {
+ AcpiMadtGenericRedistributor *gicr = acpi_data_push(table_data,
+ sizeof *gicr);
+
+ gicr->type = ACPI_APIC_GENERIC_REDISTRIBUTOR;
+ gicr->length = sizeof(*gicr);
+ gicr->base_address = cpu_to_le64(memmap[VIRT_GIC_REDIST].base);
+ gicr->range_length = cpu_to_le32(memmap[VIRT_GIC_REDIST].size);
+ } else {
+ for (i = 0; i < guest_info->smp_cpus; i++) {
+ AcpiMadtGenericInterrupt *gicc = acpi_data_push(table_data,
+ sizeof *gicc);
+ gicc->type = ACPI_APIC_GENERIC_INTERRUPT;
+ gicc->length = sizeof(*gicc);
+ gicc->base_address = memmap[VIRT_GIC_CPU].base;
+ gicc->cpu_interface_number = i;
+ gicc->arm_mpidr = i;
+ gicc->uid = i;
+ if (test_bit(i, cpuinfo->found_cpus)) {
+ gicc->flags = cpu_to_le32(ACPI_GICC_ENABLED);
+ }
+ }
+
+ gic_msi = acpi_data_push(table_data, sizeof *gic_msi);
+ gic_msi->type = ACPI_APIC_GENERIC_MSI_FRAME;
+ gic_msi->length = sizeof(*gic_msi);
+ gic_msi->gic_msi_frame_id = 0;
+ gic_msi->base_address = cpu_to_le64(memmap[VIRT_GIC_V2M].base);
+ gic_msi->flags = cpu_to_le32(1);
+ gic_msi->spi_count = cpu_to_le16(NUM_GICV2M_SPIS);
+ gic_msi->spi_base = cpu_to_le16(irqmap[VIRT_GIC_V2M] + ARM_SPI_BASE);
+ }
build_header(linker, table_data,
(void *)(table_data->data + madt_start), "APIC",
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index 6bf0d6d591..d25d6cfce7 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -51,6 +51,7 @@
#include "hw/intc/arm_gic_common.h"
#include "kvm_arm.h"
#include "hw/smbios/smbios.h"
+#include "qapi/visitor.h"
/* Number of external interrupt lines to configure the GIC with */
#define NUM_IRQS 256
@@ -81,6 +82,7 @@ typedef struct {
MachineState parent;
bool secure;
bool highmem;
+ int32_t gic_version;
} VirtMachineState;
#define TYPE_VIRT_MACHINE MACHINE_TYPE_NAME("virt")
@@ -111,6 +113,10 @@ static const MemMapEntry a15memmap[] = {
[VIRT_GIC_DIST] = { 0x08000000, 0x00010000 },
[VIRT_GIC_CPU] = { 0x08010000, 0x00010000 },
[VIRT_GIC_V2M] = { 0x08020000, 0x00001000 },
+ /* The space in between here is reserved for GICv3 CPU/vCPU/HYP */
+ [VIRT_GIC_ITS] = { 0x08080000, 0x00020000 },
+ /* This redistributor space allows up to 2*64kB*123 CPUs */
+ [VIRT_GIC_REDIST] = { 0x080A0000, 0x00F60000 },
[VIRT_UART] = { 0x09000000, 0x00001000 },
[VIRT_RTC] = { 0x09010000, 0x00001000 },
[VIRT_FW_CFG] = { 0x09020000, 0x0000000a },
@@ -255,7 +261,7 @@ static void fdt_add_psci_node(const VirtBoardInfo *vbi)
qemu_fdt_setprop_cell(fdt, "/psci", "migrate", migrate_fn);
}
-static void fdt_add_timer_nodes(const VirtBoardInfo *vbi)
+static void fdt_add_timer_nodes(const VirtBoardInfo *vbi, int gictype)
{
/* Note that on A15 h/w these interrupts are level-triggered,
* but for the GIC implementation provided by both QEMU and KVM
@@ -264,8 +270,11 @@ static void fdt_add_timer_nodes(const VirtBoardInfo *vbi)
ARMCPU *armcpu;
uint32_t irqflags = GIC_FDT_IRQ_FLAGS_EDGE_LO_HI;
- irqflags = deposit32(irqflags, GIC_FDT_IRQ_PPI_CPU_START,
- GIC_FDT_IRQ_PPI_CPU_WIDTH, (1 << vbi->smp_cpus) - 1);
+ if (gictype == 2) {
+ irqflags = deposit32(irqflags, GIC_FDT_IRQ_PPI_CPU_START,
+ GIC_FDT_IRQ_PPI_CPU_WIDTH,
+ (1 << vbi->smp_cpus) - 1);
+ }
qemu_fdt_add_subnode(vbi->fdt, "/timer");
@@ -355,25 +364,36 @@ static void fdt_add_v2m_gic_node(VirtBoardInfo *vbi)
qemu_fdt_setprop_cell(vbi->fdt, "/intc/v2m", "phandle", vbi->v2m_phandle);
}
-static void fdt_add_gic_node(VirtBoardInfo *vbi)
+static void fdt_add_gic_node(VirtBoardInfo *vbi, int type)
{
vbi->gic_phandle = qemu_fdt_alloc_phandle(vbi->fdt);
qemu_fdt_setprop_cell(vbi->fdt, "/", "interrupt-parent", vbi->gic_phandle);
qemu_fdt_add_subnode(vbi->fdt, "/intc");
- /* 'cortex-a15-gic' means 'GIC v2' */
- qemu_fdt_setprop_string(vbi->fdt, "/intc", "compatible",
- "arm,cortex-a15-gic");
qemu_fdt_setprop_cell(vbi->fdt, "/intc", "#interrupt-cells", 3);
qemu_fdt_setprop(vbi->fdt, "/intc", "interrupt-controller", NULL, 0);
- qemu_fdt_setprop_sized_cells(vbi->fdt, "/intc", "reg",
- 2, vbi->memmap[VIRT_GIC_DIST].base,
- 2, vbi->memmap[VIRT_GIC_DIST].size,
- 2, vbi->memmap[VIRT_GIC_CPU].base,
- 2, vbi->memmap[VIRT_GIC_CPU].size);
qemu_fdt_setprop_cell(vbi->fdt, "/intc", "#address-cells", 0x2);
qemu_fdt_setprop_cell(vbi->fdt, "/intc", "#size-cells", 0x2);
qemu_fdt_setprop(vbi->fdt, "/intc", "ranges", NULL, 0);
+ if (type == 3) {
+ qemu_fdt_setprop_string(vbi->fdt, "/intc", "compatible",
+ "arm,gic-v3");
+ qemu_fdt_setprop_sized_cells(vbi->fdt, "/intc", "reg",
+ 2, vbi->memmap[VIRT_GIC_DIST].base,
+ 2, vbi->memmap[VIRT_GIC_DIST].size,
+ 2, vbi->memmap[VIRT_GIC_REDIST].base,
+ 2, vbi->memmap[VIRT_GIC_REDIST].size);
+ } else {
+ /* 'cortex-a15-gic' means 'GIC v2' */
+ qemu_fdt_setprop_string(vbi->fdt, "/intc", "compatible",
+ "arm,cortex-a15-gic");
+ qemu_fdt_setprop_sized_cells(vbi->fdt, "/intc", "reg",
+ 2, vbi->memmap[VIRT_GIC_DIST].base,
+ 2, vbi->memmap[VIRT_GIC_DIST].size,
+ 2, vbi->memmap[VIRT_GIC_CPU].base,
+ 2, vbi->memmap[VIRT_GIC_CPU].size);
+ }
+
qemu_fdt_setprop_cell(vbi->fdt, "/intc", "phandle", vbi->gic_phandle);
}
@@ -396,18 +416,18 @@ static void create_v2m(VirtBoardInfo *vbi, qemu_irq *pic)
fdt_add_v2m_gic_node(vbi);
}
-static void create_gic(VirtBoardInfo *vbi, qemu_irq *pic, bool secure)
+static void create_gic(VirtBoardInfo *vbi, qemu_irq *pic, int type, bool secure)
{
- /* We create a standalone GIC v2 */
+ /* We create a standalone GIC */
DeviceState *gicdev;
SysBusDevice *gicbusdev;
const char *gictype;
int i;
- gictype = gic_class_name();
+ gictype = (type == 3) ? gicv3_class_name() : gic_class_name();
gicdev = qdev_create(NULL, gictype);
- qdev_prop_set_uint32(gicdev, "revision", 2);
+ qdev_prop_set_uint32(gicdev, "revision", type);
qdev_prop_set_uint32(gicdev, "num-cpu", smp_cpus);
/* Note that the num-irq property counts both internal and external
* interrupts; there are always 32 of the former (mandated by GIC spec).
@@ -419,7 +439,11 @@ static void create_gic(VirtBoardInfo *vbi, qemu_irq *pic, bool secure)
qdev_init_nofail(gicdev);
gicbusdev = SYS_BUS_DEVICE(gicdev);
sysbus_mmio_map(gicbusdev, 0, vbi->memmap[VIRT_GIC_DIST].base);
- sysbus_mmio_map(gicbusdev, 1, vbi->memmap[VIRT_GIC_CPU].base);
+ if (type == 3) {
+ sysbus_mmio_map(gicbusdev, 1, vbi->memmap[VIRT_GIC_REDIST].base);
+ } else {
+ sysbus_mmio_map(gicbusdev, 1, vbi->memmap[VIRT_GIC_CPU].base);
+ }
/* Wire the outputs from each CPU's generic timer to the
* appropriate GIC PPI inputs, and the GIC's IRQ output to
@@ -454,9 +478,11 @@ static void create_gic(VirtBoardInfo *vbi, qemu_irq *pic, bool secure)
pic[i] = qdev_get_gpio_in(gicdev, i);
}
- fdt_add_gic_node(vbi);
+ fdt_add_gic_node(vbi, type);
- create_v2m(vbi, pic);
+ if (type == 2) {
+ create_v2m(vbi, pic);
+ }
}
static void create_uart(const VirtBoardInfo *vbi, qemu_irq *pic)
@@ -773,7 +799,10 @@ static void create_pcie(const VirtBoardInfo *vbi, qemu_irq *pic,
qemu_fdt_setprop_cells(vbi->fdt, nodename, "bus-range", 0,
nr_pcie_buses - 1);
- qemu_fdt_setprop_cells(vbi->fdt, nodename, "msi-parent", vbi->v2m_phandle);
+ if (vbi->v2m_phandle) {
+ qemu_fdt_setprop_cells(vbi->fdt, nodename, "msi-parent",
+ vbi->v2m_phandle);
+ }
qemu_fdt_setprop_sized_cells(vbi->fdt, nodename, "reg",
2, base_ecam, 2, size_ecam);
@@ -888,6 +917,7 @@ static void machvirt_init(MachineState *machine)
VirtMachineState *vms = VIRT_MACHINE(machine);
qemu_irq pic[NUM_IRQS];
MemoryRegion *sysmem = get_system_memory();
+ int gic_version = vms->gic_version;
int n;
MemoryRegion *ram = g_new(MemoryRegion, 1);
const char *cpu_model = machine->cpu_model;
@@ -900,6 +930,18 @@ static void machvirt_init(MachineState *machine)
cpu_model = "cortex-a15";
}
+ /* We can probe only here because during property set
+ * KVM is not available yet
+ */
+ if (!gic_version) {
+ gic_version = kvm_arm_vgic_probe();
+ if (!gic_version) {
+ error_report("Unable to determine GIC version supported by host\n"
+ "Probably KVM acceleration is not supported\n");
+ exit(1);
+ }
+ }
+
/* Separate the actual CPU model name from any appended features */
cpustr = g_strsplit(cpu_model, ",", 2);
@@ -960,7 +1002,7 @@ static void machvirt_init(MachineState *machine)
object_property_set_bool(cpuobj, true, "realized", NULL);
}
g_strfreev(cpustr);
- fdt_add_timer_nodes(vbi);
+ fdt_add_timer_nodes(vbi, gic_version);
fdt_add_cpu_nodes(vbi);
fdt_add_psci_node(vbi);
@@ -970,7 +1012,7 @@ static void machvirt_init(MachineState *machine)
create_flash(vbi);
- create_gic(vbi, pic, vms->secure);
+ create_gic(vbi, pic, gic_version, vms->secure);
create_uart(vbi, pic);
@@ -992,6 +1034,7 @@ static void machvirt_init(MachineState *machine)
guest_info->memmap = vbi->memmap;
guest_info->irqmap = vbi->irqmap;
guest_info->use_highmem = vms->highmem;
+ guest_info->gic_version = gic_version;
guest_info_state->machine_done.notify = virt_guest_info_machine_done;
qemu_add_machine_init_done_notifier(&guest_info_state->machine_done);
@@ -1043,6 +1086,31 @@ static void virt_set_highmem(Object *obj, bool value, Error **errp)
vms->highmem = value;
}
+static char *virt_get_gic_version(Object *obj, Error **errp)
+{
+ VirtMachineState *vms = VIRT_MACHINE(obj);
+ const char *val = vms->gic_version == 3 ? "3" : "2";
+
+ return g_strdup(val);
+}
+
+static void virt_set_gic_version(Object *obj, const char *value, Error **errp)
+{
+ VirtMachineState *vms = VIRT_MACHINE(obj);
+
+ if (!strcmp(value, "3")) {
+ vms->gic_version = 3;
+ } else if (!strcmp(value, "2")) {
+ vms->gic_version = 2;
+ } else if (!strcmp(value, "host")) {
+ vms->gic_version = 0; /* Will probe later */
+ } else {
+ error_report("Invalid gic-version option value\n"
+ "Allowed values are: 3, 2, host\n");
+ exit(1);
+ }
+}
+
static void virt_instance_init(Object *obj)
{
VirtMachineState *vms = VIRT_MACHINE(obj);
@@ -1067,6 +1135,13 @@ static void virt_instance_init(Object *obj)
"Set on/off to enable/disable using "
"physical address space above 32 bits",
NULL);
+ /* Default GIC type is v2 */
+ vms->gic_version = 2;
+ object_property_add_str(obj, "gic-version", virt_get_gic_version,
+ virt_set_gic_version, NULL);
+ object_property_set_description(obj, "gic-version",
+ "Set GIC version. "
+ "Valid values are 2, 3 and host", NULL);
}
static void virt_class_init(ObjectClass *oc, void *data)
@@ -1075,7 +1150,10 @@ static void virt_class_init(ObjectClass *oc, void *data)
mc->desc = "ARM Virtual Machine",
mc->init = machvirt_init;
- mc->max_cpus = 8;
+ /* Our maximum number of CPUs depends on how many redistributors
+ * we can fit into memory map
+ */
+ mc->max_cpus = a15memmap[VIRT_GIC_REDIST].size / 0x20000;
mc->has_dynamic_sysbus = true;
mc->block_default_type = IF_VIRTIO;
mc->no_cdrom = 1;
diff --git a/hw/intc/Makefile.objs b/hw/intc/Makefile.objs
index 092d8a80ac..004b0c25e4 100644
--- a/hw/intc/Makefile.objs
+++ b/hw/intc/Makefile.objs
@@ -12,10 +12,12 @@ common-obj-$(CONFIG_IOAPIC) += ioapic_common.o
common-obj-$(CONFIG_ARM_GIC) += arm_gic_common.o
common-obj-$(CONFIG_ARM_GIC) += arm_gic.o
common-obj-$(CONFIG_ARM_GIC) += arm_gicv2m.o
+common-obj-$(CONFIG_ARM_GIC) += arm_gicv3_common.o
common-obj-$(CONFIG_OPENPIC) += openpic.o
obj-$(CONFIG_APIC) += apic.o apic_common.o
obj-$(CONFIG_ARM_GIC_KVM) += arm_gic_kvm.o
+obj-$(call land,$(CONFIG_ARM_GIC_KVM),$(TARGET_AARCH64)) += arm_gicv3_kvm.o
obj-$(CONFIG_STELLARIS) += armv7m_nvic.o
obj-$(CONFIG_EXYNOS4) += exynos4210_gic.o exynos4210_combiner.o
obj-$(CONFIG_GRLIB) += grlib_irqmp.o
diff --git a/hw/intc/arm_gic_kvm.c b/hw/intc/arm_gic_kvm.c
index e5d0f67186..e8b2386908 100644
--- a/hw/intc/arm_gic_kvm.c
+++ b/hw/intc/arm_gic_kvm.c
@@ -23,6 +23,7 @@
#include "sysemu/kvm.h"
#include "kvm_arm.h"
#include "gic_internal.h"
+#include "vgic_common.h"
//#define DEBUG_GIC_KVM
@@ -52,7 +53,7 @@ typedef struct KVMARMGICClass {
void (*parent_reset)(DeviceState *dev);
} KVMARMGICClass;
-static void kvm_arm_gic_set_irq(void *opaque, int irq, int level)
+void kvm_arm_gic_set_irq(uint32_t num_irq, int irq, int level)
{
/* Meaning of the 'irq' parameter:
* [0..N-1] : external interrupts
@@ -63,10 +64,9 @@ static void kvm_arm_gic_set_irq(void *opaque, int irq, int level)
* has separate fields in the irq number for type,
* CPU number and interrupt number.
*/
- GICState *s = (GICState *)opaque;
int kvm_irq, irqtype, cpu;
- if (irq < (s->num_irq - GIC_INTERNAL)) {
+ if (irq < (num_irq - GIC_INTERNAL)) {
/* External interrupt. The kernel numbers these like the GIC
* hardware, with external interrupt IDs starting after the
* internal ones.
@@ -77,7 +77,7 @@ static void kvm_arm_gic_set_irq(void *opaque, int irq, int level)
} else {
/* Internal interrupt: decode into (cpu, interrupt id) */
irqtype = KVM_ARM_IRQ_TYPE_PPI;
- irq -= (s->num_irq - GIC_INTERNAL);
+ irq -= (num_irq - GIC_INTERNAL);
cpu = irq / GIC_INTERNAL;
irq %= GIC_INTERNAL;
}
@@ -87,69 +87,36 @@ static void kvm_arm_gic_set_irq(void *opaque, int irq, int level)
kvm_set_irq(kvm_state, kvm_irq, !!level);
}
-static bool kvm_arm_gic_can_save_restore(GICState *s)
-{
- return s->dev_fd >= 0;
-}
-
-static bool kvm_gic_supports_attr(GICState *s, int group, int attrnum)
+static void kvm_arm_gicv2_set_irq(void *opaque, int irq, int level)
{
- struct kvm_device_attr attr = {
- .group = group,
- .attr = attrnum,
- .flags = 0,
- };
-
- if (s->dev_fd == -1) {
- return false;
- }
+ GICState *s = (GICState *)opaque;
- return kvm_device_ioctl(s->dev_fd, KVM_HAS_DEVICE_ATTR, &attr) == 0;
+ kvm_arm_gic_set_irq(s->num_irq, irq, level);
}
-static void kvm_gic_access(GICState *s, int group, int offset,
- int cpu, uint32_t *val, bool write)
+static bool kvm_arm_gic_can_save_restore(GICState *s)
{
- struct kvm_device_attr attr;
- int type;
- int err;
-
- cpu = cpu & 0xff;
-
- attr.flags = 0;
- attr.group = group;
- attr.attr = (((uint64_t)cpu << KVM_DEV_ARM_VGIC_CPUID_SHIFT) &
- KVM_DEV_ARM_VGIC_CPUID_MASK) |
- (((uint64_t)offset << KVM_DEV_ARM_VGIC_OFFSET_SHIFT) &
- KVM_DEV_ARM_VGIC_OFFSET_MASK);
- attr.addr = (uintptr_t)val;
-
- if (write) {
- type = KVM_SET_DEVICE_ATTR;
- } else {
- type = KVM_GET_DEVICE_ATTR;
- }
-
- err = kvm_device_ioctl(s->dev_fd, type, &attr);
- if (err < 0) {
- fprintf(stderr, "KVM_{SET/GET}_DEVICE_ATTR failed: %s\n",
- strerror(-err));
- abort();
- }
+ return s->dev_fd >= 0;
}
+#define KVM_VGIC_ATTR(offset, cpu) \
+ ((((uint64_t)(cpu) << KVM_DEV_ARM_VGIC_CPUID_SHIFT) & \
+ KVM_DEV_ARM_VGIC_CPUID_MASK) | \
+ (((uint64_t)(offset) << KVM_DEV_ARM_VGIC_OFFSET_SHIFT) & \
+ KVM_DEV_ARM_VGIC_OFFSET_MASK))
+
static void kvm_gicd_access(GICState *s, int offset, int cpu,
uint32_t *val, bool write)
{
- kvm_gic_access(s, KVM_DEV_ARM_VGIC_GRP_DIST_REGS,
- offset, cpu, val, write);
+ kvm_device_access(s->dev_fd, KVM_DEV_ARM_VGIC_GRP_DIST_REGS,
+ KVM_VGIC_ATTR(offset, cpu), val, write);
}
static void kvm_gicc_access(GICState *s, int offset, int cpu,
uint32_t *val, bool write)
{
- kvm_gic_access(s, KVM_DEV_ARM_VGIC_GRP_CPU_REGS,
- offset, cpu, val, write);
+ kvm_device_access(s->dev_fd, KVM_DEV_ARM_VGIC_GRP_CPU_REGS,
+ KVM_VGIC_ATTR(offset, cpu), val, write);
}
#define for_each_irq_reg(_ctr, _max_irq, _field_width) \
@@ -559,7 +526,7 @@ static void kvm_arm_gic_realize(DeviceState *dev, Error **errp)
return;
}
- gic_init_irqs_and_mmio(s, kvm_arm_gic_set_irq, NULL);
+ gic_init_irqs_and_mmio(s, kvm_arm_gicv2_set_irq, NULL);
for (i = 0; i < s->num_irq - GIC_INTERNAL; i++) {
qemu_irq irq = qdev_get_gpio_in(dev, i);
@@ -571,23 +538,24 @@ static void kvm_arm_gic_realize(DeviceState *dev, Error **errp)
ret = kvm_create_device(kvm_state, KVM_DEV_TYPE_ARM_VGIC_V2, false);
if (ret >= 0) {
s->dev_fd = ret;
+
+ /* Newstyle API is used, we may have attributes */
+ if (kvm_device_check_attr(s->dev_fd, KVM_DEV_ARM_VGIC_GRP_NR_IRQS, 0)) {
+ uint32_t numirqs = s->num_irq;
+ kvm_device_access(s->dev_fd, KVM_DEV_ARM_VGIC_GRP_NR_IRQS, 0,
+ &numirqs, true);
+ }
+ /* Tell the kernel to complete VGIC initialization now */
+ if (kvm_device_check_attr(s->dev_fd, KVM_DEV_ARM_VGIC_GRP_CTRL,
+ KVM_DEV_ARM_VGIC_CTRL_INIT)) {
+ kvm_device_access(s->dev_fd, KVM_DEV_ARM_VGIC_GRP_CTRL,
+ KVM_DEV_ARM_VGIC_CTRL_INIT, NULL, true);
+ }
} else if (ret != -ENODEV && ret != -ENOTSUP) {
error_setg_errno(errp, -ret, "error creating in-kernel VGIC");
return;
}
- if (kvm_gic_supports_attr(s, KVM_DEV_ARM_VGIC_GRP_NR_IRQS, 0)) {
- uint32_t numirqs = s->num_irq;
- kvm_gic_access(s, KVM_DEV_ARM_VGIC_GRP_NR_IRQS, 0, 0, &numirqs, 1);
- }
-
- /* Tell the kernel to complete VGIC initialization now */
- if (kvm_gic_supports_attr(s, KVM_DEV_ARM_VGIC_GRP_CTRL,
- KVM_DEV_ARM_VGIC_CTRL_INIT)) {
- kvm_gic_access(s, KVM_DEV_ARM_VGIC_GRP_CTRL,
- KVM_DEV_ARM_VGIC_CTRL_INIT, 0, 0, 1);
- }
-
/* Distributor */
kvm_arm_register_device(&s->iomem,
(KVM_ARM_DEVICE_VGIC_V2 << KVM_ARM_DEVICE_ID_SHIFT)
diff --git a/hw/intc/arm_gicv3_common.c b/hw/intc/arm_gicv3_common.c
new file mode 100644
index 0000000000..032ece2166
--- /dev/null
+++ b/hw/intc/arm_gicv3_common.c
@@ -0,0 +1,140 @@
+/*
+ * ARM GICv3 support - common bits of emulated and KVM kernel model
+ *
+ * Copyright (c) 2012 Linaro Limited
+ * Copyright (c) 2015 Huawei.
+ * Written by Peter Maydell
+ * Extended to 64 cores by Shlomo Pongratz
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "hw/intc/arm_gicv3_common.h"
+
+static void gicv3_pre_save(void *opaque)
+{
+ GICv3State *s = (GICv3State *)opaque;
+ ARMGICv3CommonClass *c = ARM_GICV3_COMMON_GET_CLASS(s);
+
+ if (c->pre_save) {
+ c->pre_save(s);
+ }
+}
+
+static int gicv3_post_load(void *opaque, int version_id)
+{
+ GICv3State *s = (GICv3State *)opaque;
+ ARMGICv3CommonClass *c = ARM_GICV3_COMMON_GET_CLASS(s);
+
+ if (c->post_load) {
+ c->post_load(s);
+ }
+ return 0;
+}
+
+static const VMStateDescription vmstate_gicv3 = {
+ .name = "arm_gicv3",
+ .unmigratable = 1,
+ .pre_save = gicv3_pre_save,
+ .post_load = gicv3_post_load,
+};
+
+void gicv3_init_irqs_and_mmio(GICv3State *s, qemu_irq_handler handler,
+ const MemoryRegionOps *ops)
+{
+ SysBusDevice *sbd = SYS_BUS_DEVICE(s);
+ int i;
+
+ /* For the GIC, also expose incoming GPIO lines for PPIs for each CPU.
+ * GPIO array layout is thus:
+ * [0..N-1] spi
+ * [N..N+31] PPIs for CPU 0
+ * [N+32..N+63] PPIs for CPU 1
+ * ...
+ */
+ i = s->num_irq - GIC_INTERNAL + GIC_INTERNAL * s->num_cpu;
+ qdev_init_gpio_in(DEVICE(s), handler, i);
+
+ s->parent_irq = g_malloc(s->num_cpu * sizeof(qemu_irq));
+ s->parent_fiq = g_malloc(s->num_cpu * sizeof(qemu_irq));
+
+ for (i = 0; i < s->num_cpu; i++) {
+ sysbus_init_irq(sbd, &s->parent_irq[i]);
+ }
+ for (i = 0; i < s->num_cpu; i++) {
+ sysbus_init_irq(sbd, &s->parent_fiq[i]);
+ }
+
+ memory_region_init_io(&s->iomem_dist, OBJECT(s), ops, s,
+ "gicv3_dist", 0x10000);
+ memory_region_init_io(&s->iomem_redist, OBJECT(s), ops ? &ops[1] : NULL, s,
+ "gicv3_redist", 0x20000 * s->num_cpu);
+
+ sysbus_init_mmio(sbd, &s->iomem_dist);
+ sysbus_init_mmio(sbd, &s->iomem_redist);
+}
+
+static void arm_gicv3_common_realize(DeviceState *dev, Error **errp)
+{
+ GICv3State *s = ARM_GICV3_COMMON(dev);
+
+ /* revision property is actually reserved and currently used only in order
+ * to keep the interface compatible with GICv2 code, avoiding extra
+ * conditions. However, in future it could be used, for example, if we
+ * implement GICv4.
+ */
+ if (s->revision != 3) {
+ error_setg(errp, "unsupported GIC revision %d", s->revision);
+ return;
+ }
+}
+
+static void arm_gicv3_common_reset(DeviceState *dev)
+{
+ /* TODO */
+}
+
+static Property arm_gicv3_common_properties[] = {
+ DEFINE_PROP_UINT32("num-cpu", GICv3State, num_cpu, 1),
+ DEFINE_PROP_UINT32("num-irq", GICv3State, num_irq, 32),
+ DEFINE_PROP_UINT32("revision", GICv3State, revision, 3),
+ DEFINE_PROP_BOOL("has-security-extensions", GICv3State, security_extn, 0),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static void arm_gicv3_common_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+
+ dc->reset = arm_gicv3_common_reset;
+ dc->realize = arm_gicv3_common_realize;
+ dc->props = arm_gicv3_common_properties;
+ dc->vmsd = &vmstate_gicv3;
+}
+
+static const TypeInfo arm_gicv3_common_type = {
+ .name = TYPE_ARM_GICV3_COMMON,
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(GICv3State),
+ .class_size = sizeof(ARMGICv3CommonClass),
+ .class_init = arm_gicv3_common_class_init,
+ .abstract = true,
+};
+
+static void register_types(void)
+{
+ type_register_static(&arm_gicv3_common_type);
+}
+
+type_init(register_types)
diff --git a/hw/intc/arm_gicv3_kvm.c b/hw/intc/arm_gicv3_kvm.c
new file mode 100644
index 0000000000..b48f78f13d
--- /dev/null
+++ b/hw/intc/arm_gicv3_kvm.c
@@ -0,0 +1,149 @@
+/*
+ * ARM Generic Interrupt Controller using KVM in-kernel support
+ *
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ * Written by Pavel Fedin
+ * Based on vGICv2 code by Peter Maydell
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "hw/intc/arm_gicv3_common.h"
+#include "hw/sysbus.h"
+#include "sysemu/kvm.h"
+#include "kvm_arm.h"
+#include "vgic_common.h"
+
+#ifdef DEBUG_GICV3_KVM
+#define DPRINTF(fmt, ...) \
+ do { fprintf(stderr, "kvm_gicv3: " fmt, ## __VA_ARGS__); } while (0)
+#else
+#define DPRINTF(fmt, ...) \
+ do { } while (0)
+#endif
+
+#define TYPE_KVM_ARM_GICV3 "kvm-arm-gicv3"
+#define KVM_ARM_GICV3(obj) \
+ OBJECT_CHECK(GICv3State, (obj), TYPE_KVM_ARM_GICV3)
+#define KVM_ARM_GICV3_CLASS(klass) \
+ OBJECT_CLASS_CHECK(KVMARMGICv3Class, (klass), TYPE_KVM_ARM_GICV3)
+#define KVM_ARM_GICV3_GET_CLASS(obj) \
+ OBJECT_GET_CLASS(KVMARMGICv3Class, (obj), TYPE_KVM_ARM_GICV3)
+
+typedef struct KVMARMGICv3Class {
+ ARMGICv3CommonClass parent_class;
+ DeviceRealize parent_realize;
+ void (*parent_reset)(DeviceState *dev);
+} KVMARMGICv3Class;
+
+static void kvm_arm_gicv3_set_irq(void *opaque, int irq, int level)
+{
+ GICv3State *s = (GICv3State *)opaque;
+
+ kvm_arm_gic_set_irq(s->num_irq, irq, level);
+}
+
+static void kvm_arm_gicv3_put(GICv3State *s)
+{
+ /* TODO */
+ DPRINTF("Cannot put kernel gic state, no kernel interface\n");
+}
+
+static void kvm_arm_gicv3_get(GICv3State *s)
+{
+ /* TODO */
+ DPRINTF("Cannot get kernel gic state, no kernel interface\n");
+}
+
+static void kvm_arm_gicv3_reset(DeviceState *dev)
+{
+ GICv3State *s = ARM_GICV3_COMMON(dev);
+ KVMARMGICv3Class *kgc = KVM_ARM_GICV3_GET_CLASS(s);
+
+ DPRINTF("Reset\n");
+
+ kgc->parent_reset(dev);
+ kvm_arm_gicv3_put(s);
+}
+
+static void kvm_arm_gicv3_realize(DeviceState *dev, Error **errp)
+{
+ GICv3State *s = KVM_ARM_GICV3(dev);
+ KVMARMGICv3Class *kgc = KVM_ARM_GICV3_GET_CLASS(s);
+ Error *local_err = NULL;
+
+ DPRINTF("kvm_arm_gicv3_realize\n");
+
+ kgc->parent_realize(dev, &local_err);
+ if (local_err) {
+ error_propagate(errp, local_err);
+ return;
+ }
+
+ if (s->security_extn) {
+ error_setg(errp, "the in-kernel VGICv3 does not implement the "
+ "security extensions");
+ return;
+ }
+
+ gicv3_init_irqs_and_mmio(s, kvm_arm_gicv3_set_irq, NULL);
+
+ /* Try to create the device via the device control API */
+ s->dev_fd = kvm_create_device(kvm_state, KVM_DEV_TYPE_ARM_VGIC_V3, false);
+ if (s->dev_fd < 0) {
+ error_setg_errno(errp, -s->dev_fd, "error creating in-kernel VGIC");
+ return;
+ }
+
+ kvm_device_access(s->dev_fd, KVM_DEV_ARM_VGIC_GRP_NR_IRQS,
+ 0, &s->num_irq, true);
+
+ /* Tell the kernel to complete VGIC initialization now */
+ kvm_device_access(s->dev_fd, KVM_DEV_ARM_VGIC_GRP_CTRL,
+ KVM_DEV_ARM_VGIC_CTRL_INIT, NULL, true);
+
+ kvm_arm_register_device(&s->iomem_dist, -1, KVM_DEV_ARM_VGIC_GRP_ADDR,
+ KVM_VGIC_V3_ADDR_TYPE_DIST, s->dev_fd);
+ kvm_arm_register_device(&s->iomem_redist, -1, KVM_DEV_ARM_VGIC_GRP_ADDR,
+ KVM_VGIC_V3_ADDR_TYPE_REDIST, s->dev_fd);
+}
+
+static void kvm_arm_gicv3_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ ARMGICv3CommonClass *agcc = ARM_GICV3_COMMON_CLASS(klass);
+ KVMARMGICv3Class *kgc = KVM_ARM_GICV3_CLASS(klass);
+
+ agcc->pre_save = kvm_arm_gicv3_get;
+ agcc->post_load = kvm_arm_gicv3_put;
+ kgc->parent_realize = dc->realize;
+ kgc->parent_reset = dc->reset;
+ dc->realize = kvm_arm_gicv3_realize;
+ dc->reset = kvm_arm_gicv3_reset;
+}
+
+static const TypeInfo kvm_arm_gicv3_info = {
+ .name = TYPE_KVM_ARM_GICV3,
+ .parent = TYPE_ARM_GICV3_COMMON,
+ .instance_size = sizeof(GICv3State),
+ .class_init = kvm_arm_gicv3_class_init,
+ .class_size = sizeof(KVMARMGICv3Class),
+};
+
+static void kvm_arm_gicv3_register_types(void)
+{
+ type_register_static(&kvm_arm_gicv3_info);
+}
+
+type_init(kvm_arm_gicv3_register_types)
diff --git a/hw/intc/vgic_common.h b/hw/intc/vgic_common.h
new file mode 100644
index 0000000000..80d919eb93
--- /dev/null
+++ b/hw/intc/vgic_common.h
@@ -0,0 +1,35 @@
+/*
+ * ARM KVM vGIC utility functions
+ *
+ * Copyright (c) 2015 Samsung Electronics
+ * Written by Pavel Fedin
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef QEMU_ARM_VGIC_COMMON_H
+#define QEMU_ARM_VGIC_COMMON_H
+
+/**
+ * kvm_arm_gic_set_irq - Send an IRQ to the in-kernel vGIC
+ * @num_irq: Total number of IRQs configured for the GIC instance
+ * @irq: qemu internal IRQ line number:
+ * [0..N-1] : external interrupts
+ * [N..N+31] : PPI (internal) interrupts for CPU 0
+ * [N+32..N+63] : PPI (internal interrupts for CPU 1
+ * @level: level of the IRQ line.
+ */
+void kvm_arm_gic_set_irq(uint32_t num_irq, int irq, int level);
+
+#endif
diff --git a/hw/usb/Makefile.objs b/hw/usb/Makefile.objs
index 7443e386b3..8f00fbd8f6 100644
--- a/hw/usb/Makefile.objs
+++ b/hw/usb/Makefile.objs
@@ -23,9 +23,8 @@ common-obj-$(CONFIG_USB_BLUETOOTH) += dev-bluetooth.o
ifeq ($(CONFIG_USB_SMARTCARD),y)
common-obj-y += dev-smartcard-reader.o
-common-obj-y += ccid-card-passthru.o
-common-obj-$(CONFIG_SMARTCARD_NSS) += ccid-card-emulated.o
-ccid-card-emulated.o-cflags := -I$(SRC_PATH)/libcacard
+common-obj-$(CONFIG_SMARTCARD) += ccid-card-passthru.o
+common-obj-$(CONFIG_SMARTCARD) += ccid-card-emulated.o
endif
ifeq ($(CONFIG_POSIX),y)
diff --git a/hw/usb/ccid-card-passthru.c b/hw/usb/ccid-card-passthru.c
index 85a4fc3e53..9f49c0537f 100644
--- a/hw/usb/ccid-card-passthru.c
+++ b/hw/usb/ccid-card-passthru.c
@@ -12,7 +12,7 @@
#include "qemu/error-report.h"
#include "qemu/sockets.h"
#include "ccid.h"
-#include "libcacard/vscard_common.h"
+#include "cacard/vscard_common.h"
#define DPRINTF(card, lvl, fmt, ...) \
do { \
diff --git a/include/hw/acpi/acpi-defs.h b/include/hw/acpi/acpi-defs.h
index 2b431e6242..c7a03d43b9 100644
--- a/include/hw/acpi/acpi-defs.h
+++ b/include/hw/acpi/acpi-defs.h
@@ -384,6 +384,15 @@ struct AcpiMadtGenericMsiFrame {
typedef struct AcpiMadtGenericMsiFrame AcpiMadtGenericMsiFrame;
+struct AcpiMadtGenericRedistributor {
+ ACPI_SUB_HEADER_DEF
+ uint16_t reserved;
+ uint64_t base_address;
+ uint32_t range_length;
+} QEMU_PACKED;
+
+typedef struct AcpiMadtGenericRedistributor AcpiMadtGenericRedistributor;
+
/*
* Generic Timer Description Table (GTDT)
*/
diff --git a/include/hw/arm/virt-acpi-build.h b/include/hw/arm/virt-acpi-build.h
index 19b68a404e..744b666385 100644
--- a/include/hw/arm/virt-acpi-build.h
+++ b/include/hw/arm/virt-acpi-build.h
@@ -32,6 +32,7 @@ typedef struct VirtGuestInfo {
const MemMapEntry *memmap;
const int *irqmap;
bool use_highmem;
+ int gic_version;
} VirtGuestInfo;
diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h
index 808753f08e..f464586304 100644
--- a/include/hw/arm/virt.h
+++ b/include/hw/arm/virt.h
@@ -46,6 +46,9 @@ enum {
VIRT_CPUPERIPHS,
VIRT_GIC_DIST,
VIRT_GIC_CPU,
+ VIRT_GIC_V2M,
+ VIRT_GIC_ITS,
+ VIRT_GIC_REDIST,
VIRT_UART,
VIRT_MMIO,
VIRT_RTC,
@@ -54,7 +57,6 @@ enum {
VIRT_PCIE_MMIO,
VIRT_PCIE_PIO,
VIRT_PCIE_ECAM,
- VIRT_GIC_V2M,
VIRT_PLATFORM_BUS,
VIRT_PCIE_MMIO_HIGH,
};
diff --git a/include/hw/intc/arm_gicv3_common.h b/include/hw/intc/arm_gicv3_common.h
new file mode 100644
index 0000000000..c2fd8da4ef
--- /dev/null
+++ b/include/hw/intc/arm_gicv3_common.h
@@ -0,0 +1,68 @@
+/*
+ * ARM GIC support
+ *
+ * Copyright (c) 2012 Linaro Limited
+ * Copyright (c) 2015 Huawei.
+ * Written by Peter Maydell
+ * Extended to 64 cores by Shlomo Pongratz
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef HW_ARM_GICV3_COMMON_H
+#define HW_ARM_GICV3_COMMON_H
+
+#include "hw/sysbus.h"
+#include "hw/intc/arm_gic_common.h"
+
+typedef struct GICv3State {
+ /*< private >*/
+ SysBusDevice parent_obj;
+ /*< public >*/
+
+ qemu_irq *parent_irq;
+ qemu_irq *parent_fiq;
+
+ MemoryRegion iomem_dist; /* Distributor */
+ MemoryRegion iomem_redist; /* Redistributors */
+
+ uint32_t num_cpu;
+ uint32_t num_irq;
+ uint32_t revision;
+ bool security_extn;
+
+ int dev_fd; /* kvm device fd if backed by kvm vgic support */
+} GICv3State;
+
+#define TYPE_ARM_GICV3_COMMON "arm-gicv3-common"
+#define ARM_GICV3_COMMON(obj) \
+ OBJECT_CHECK(GICv3State, (obj), TYPE_ARM_GICV3_COMMON)
+#define ARM_GICV3_COMMON_CLASS(klass) \
+ OBJECT_CLASS_CHECK(ARMGICv3CommonClass, (klass), TYPE_ARM_GICV3_COMMON)
+#define ARM_GICV3_COMMON_GET_CLASS(obj) \
+ OBJECT_GET_CLASS(ARMGICv3CommonClass, (obj), TYPE_ARM_GICV3_COMMON)
+
+typedef struct ARMGICv3CommonClass {
+ /*< private >*/
+ SysBusDeviceClass parent_class;
+ /*< public >*/
+
+ void (*pre_save)(GICv3State *s);
+ void (*post_load)(GICv3State *s);
+} ARMGICv3CommonClass;
+
+void gicv3_init_irqs_and_mmio(GICv3State *s, qemu_irq_handler handler,
+ const MemoryRegionOps *ops);
+
+#endif
diff --git a/include/qemu/osdep.h b/include/qemu/osdep.h
index ab3c8766b4..ef21efb683 100644
--- a/include/qemu/osdep.h
+++ b/include/qemu/osdep.h
@@ -38,10 +38,12 @@
#include <strings.h>
#include <inttypes.h>
#include <limits.h>
+/* Put unistd.h before time.h as that triggers localtime_r/gmtime_r
+ * function availability on recentish Mingw-w64 platforms. */
+#include <unistd.h>
#include <time.h>
#include <ctype.h>
#include <errno.h>
-#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/time.h>
diff --git a/include/qemu/thread-win32.h b/include/qemu/thread-win32.h
index 3d58081bed..385ff5f76a 100644
--- a/include/qemu/thread-win32.h
+++ b/include/qemu/thread-win32.h
@@ -18,6 +18,7 @@ struct QemuSemaphore {
};
struct QemuEvent {
+ int value;
HANDLE event;
};
diff --git a/include/sysemu/kvm.h b/include/sysemu/kvm.h
index 983e99e1e7..2a58b4d19e 100644
--- a/include/sysemu/kvm.h
+++ b/include/sysemu/kvm.h
@@ -240,6 +240,32 @@ int kvm_device_ioctl(int fd, int type, ...);
int kvm_vm_check_attr(KVMState *s, uint32_t group, uint64_t attr);
/**
+ * kvm_device_check_attr - check for existence of a specific device attribute
+ * @fd: The device file descriptor
+ * @group: the group
+ * @attr: the attribute of that group to query for
+ *
+ * Returns: 1 if the attribute exists
+ * 0 if the attribute either does not exist or if the vm device
+ * interface is unavailable
+ */
+int kvm_device_check_attr(int fd, uint32_t group, uint64_t attr);
+
+/**
+ * kvm_device_access - set or get value of a specific vm attribute
+ * @fd: The device file descriptor
+ * @group: the group
+ * @attr: the attribute of that group to set or get
+ * @val: pointer to a storage area for the value
+ * @write: true for set and false for get operation
+ *
+ * This function is not allowed to fail. Use kvm_device_check_attr()
+ * in order to check for the availability of optional attributes.
+ */
+void kvm_device_access(int fd, int group, uint64_t attr,
+ void *val, bool write);
+
+/**
* kvm_create_device - create a KVM device for the device control API
* @KVMState: The KVMState pointer
* @type: The KVM device type (see Documentation/virtual/kvm/devices in the
diff --git a/include/sysemu/os-win32.h b/include/sysemu/os-win32.h
index 706d85a98e..13dcef6b4c 100644
--- a/include/sysemu/os-win32.h
+++ b/include/sysemu/os-win32.h
@@ -73,10 +73,12 @@
#define siglongjmp(env, val) longjmp(env, val)
/* Missing POSIX functions. Don't use MinGW-w64 macros. */
+#ifndef CONFIG_LOCALTIME_R
#undef gmtime_r
struct tm *gmtime_r(const time_t *timep, struct tm *result);
#undef localtime_r
struct tm *localtime_r(const time_t *timep, struct tm *result);
+#endif /* CONFIG_LOCALTIME_R */
static inline void os_setup_signal_handling(void) {}
diff --git a/include/ui/gtk.h b/include/ui/gtk.h
index ee6dffd306..0359333fce 100644
--- a/include/ui/gtk.h
+++ b/include/ui/gtk.h
@@ -1,10 +1,6 @@
#ifndef UI_GTK_H
#define UI_GTK_H
-#ifdef _WIN32
-# define _WIN32_WINNT 0x0601 /* needed to get definition of MAPVK_VK_TO_VSC */
-#endif
-
#ifdef CONFIG_PRAGMA_DIAGNOSTIC_AVAILABLE
/* Work around an -Wstrict-prototypes warning in GTK headers */
#pragma GCC diagnostic push
diff --git a/kvm-all.c b/kvm-all.c
index de1924c467..0be4615cdb 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -24,6 +24,7 @@
#include "qemu/atomic.h"
#include "qemu/option.h"
#include "qemu/config-file.h"
+#include "qemu/error-report.h"
#include "hw/hw.h"
#include "hw/pci/msi.h"
#include "hw/s390x/adapter.h"
@@ -2008,6 +2009,39 @@ int kvm_vm_check_attr(KVMState *s, uint32_t group, uint64_t attr)
return ret ? 0 : 1;
}
+int kvm_device_check_attr(int dev_fd, uint32_t group, uint64_t attr)
+{
+ struct kvm_device_attr attribute = {
+ .group = group,
+ .attr = attr,
+ .flags = 0,
+ };
+
+ return kvm_device_ioctl(dev_fd, KVM_HAS_DEVICE_ATTR, &attribute) ? 0 : 1;
+}
+
+void kvm_device_access(int fd, int group, uint64_t attr,
+ void *val, bool write)
+{
+ struct kvm_device_attr kvmattr;
+ int err;
+
+ kvmattr.flags = 0;
+ kvmattr.group = group;
+ kvmattr.attr = attr;
+ kvmattr.addr = (uintptr_t)val;
+
+ err = kvm_device_ioctl(fd,
+ write ? KVM_SET_DEVICE_ATTR : KVM_GET_DEVICE_ATTR,
+ &kvmattr);
+ if (err < 0) {
+ error_report("KVM_%s_DEVICE_ATTR failed: %s\n"
+ "Group %d attr 0x%016" PRIx64, write ? "SET" : "GET",
+ strerror(-err), group, attr);
+ abort();
+ }
+}
+
int kvm_has_sync_mmu(void)
{
return kvm_check_extension(kvm_state, KVM_CAP_SYNC_MMU);
diff --git a/libcacard/Makefile b/libcacard/Makefile
deleted file mode 100644
index b5eddff11e..0000000000
--- a/libcacard/Makefile
+++ /dev/null
@@ -1,45 +0,0 @@
-libcacard_includedir=$(includedir)/cacard
-
-TOOLS += vscclient$(EXESUF)
-
-# objects linked into a shared library, built with libtool with -fPIC if required
-libcacard-obj-y = $(libcacard-y)
-libcacard-lobj-y=$(patsubst %.o,%.lo,$(libcacard-obj-y))
-
-# libtool will build the .o files, too
-$(libcacard-obj-y): | $(libcacard-lobj-y)
-
-all: libcacard.la libcacard.pc
-
-vscclient$(EXESUF): libcacard/vscclient.o libcacard.la
- $(call LINK,$^)
-
-#########################################################################
-# Rules for building libcacard standalone library
-
-libcacard.la: LDFLAGS += -rpath $(libdir) -no-undefined \
- -export-symbols $(SRC_PATH)/libcacard/libcacard.syms
-# Prevent libcacard.so linking against the entire world of 3rd party libs
-libcacard.la: LIBS =
-libcacard.la: $(libcacard-lobj-y)
- $(call LINK,$^)
-
-libcacard.pc: $(SRC_PATH)/libcacard/libcacard.pc.in
- $(call quiet-command,sed -e 's|@LIBDIR@|$(libdir)|' \
- -e 's|@INCLUDEDIR@|$(libcacard_includedir)|' \
- -e 's|@VERSION@|$(shell cat $(SRC_PATH)/VERSION)|' \
- -e 's|@PREFIX@|$(prefix)|' $< > libcacard.pc,\
- " GEN $@")
-
-.PHONY: install-libcacard
-
-install: install-libcacard
-install-libcacard: libcacard.pc libcacard.la
- $(INSTALL_DIR) "$(DESTDIR)$(libdir)"
- $(INSTALL_DIR) "$(DESTDIR)$(libdir)/pkgconfig"
- $(INSTALL_DIR) "$(DESTDIR)$(libcacard_includedir)"
- $(INSTALL_LIB) libcacard.la "$(DESTDIR)$(libdir)"
- $(INSTALL_DATA) libcacard.pc "$(DESTDIR)$(libdir)/pkgconfig"
- for inc in $(SRC_PATH)/libcacard/*.h; do \
- $(INSTALL_DATA) $$inc "$(DESTDIR)$(libcacard_includedir)"; \
- done
diff --git a/libcacard/cac.c b/libcacard/cac.c
deleted file mode 100644
index bc84534f9c..0000000000
--- a/libcacard/cac.c
+++ /dev/null
@@ -1,414 +0,0 @@
-/*
- * implement the applets for the CAC card.
- *
- * This code is licensed under the GNU LGPL, version 2.1 or later.
- * See the COPYING.LIB file in the top-level directory.
- */
-
-#include "glib-compat.h"
-
-#include <string.h>
-#include <stdbool.h>
-
-#include "cac.h"
-#include "vcard.h"
-#include "vcard_emul.h"
-#include "card_7816.h"
-
-/* private data for PKI applets */
-typedef struct CACPKIAppletDataStruct {
- unsigned char *cert;
- int cert_len;
- unsigned char *cert_buffer;
- int cert_buffer_len;
- unsigned char *sign_buffer;
- int sign_buffer_len;
- VCardKey *key;
-} CACPKIAppletData;
-
-/*
- * CAC applet private data
- */
-struct VCardAppletPrivateStruct {
- union {
- CACPKIAppletData pki_data;
- void *reserved;
- } u;
-};
-
-/*
- * handle all the APDU's that are common to all CAC applets
- */
-static VCardStatus
-cac_common_process_apdu(VCard *card, VCardAPDU *apdu, VCardResponse **response)
-{
- int ef;
- VCardStatus ret = VCARD_FAIL;
-
- switch (apdu->a_ins) {
- case VCARD7816_INS_SELECT_FILE:
- if (apdu->a_p1 != 0x02) {
- /* let the 7816 code handle applet switches */
- ret = VCARD_NEXT;
- break;
- }
- /* handle file id setting */
- if (apdu->a_Lc != 2) {
- *response = vcard_make_response(
- VCARD7816_STATUS_ERROR_DATA_INVALID);
- ret = VCARD_DONE;
- break;
- }
- /* CAC 1.0 only supports ef = 0 */
- ef = apdu->a_body[0] | (apdu->a_body[1] << 8);
- if (ef != 0) {
- *response = vcard_make_response(
- VCARD7816_STATUS_ERROR_FILE_NOT_FOUND);
- ret = VCARD_DONE;
- break;
- }
- *response = vcard_make_response(VCARD7816_STATUS_SUCCESS);
- ret = VCARD_DONE;
- break;
- case VCARD7816_INS_GET_RESPONSE:
- case VCARD7816_INS_VERIFY:
- /* let the 7816 code handle these */
- ret = VCARD_NEXT;
- break;
- case CAC_GET_PROPERTIES:
- case CAC_GET_ACR:
- /* skip these for now, this will probably be needed */
- *response = vcard_make_response(VCARD7816_STATUS_ERROR_P1_P2_INCORRECT);
- ret = VCARD_DONE;
- break;
- default:
- *response = vcard_make_response(
- VCARD7816_STATUS_ERROR_COMMAND_NOT_SUPPORTED);
- ret = VCARD_DONE;
- break;
- }
- return ret;
-}
-
-/*
- * reset the inter call state between applet selects
- */
-static VCardStatus
-cac_applet_pki_reset(VCard *card, int channel)
-{
- VCardAppletPrivate *applet_private;
- CACPKIAppletData *pki_applet;
- applet_private = vcard_get_current_applet_private(card, channel);
- assert(applet_private);
- pki_applet = &(applet_private->u.pki_data);
-
- pki_applet->cert_buffer = NULL;
- g_free(pki_applet->sign_buffer);
- pki_applet->sign_buffer = NULL;
- pki_applet->cert_buffer_len = 0;
- pki_applet->sign_buffer_len = 0;
- return VCARD_DONE;
-}
-
-static VCardStatus
-cac_applet_pki_process_apdu(VCard *card, VCardAPDU *apdu,
- VCardResponse **response)
-{
- CACPKIAppletData *pki_applet;
- VCardAppletPrivate *applet_private;
- int size, next;
- unsigned char *sign_buffer;
- bool retain_sign_buffer = FALSE;
- vcard_7816_status_t status;
- VCardStatus ret = VCARD_FAIL;
-
- applet_private = vcard_get_current_applet_private(card, apdu->a_channel);
- assert(applet_private);
- pki_applet = &(applet_private->u.pki_data);
-
- switch (apdu->a_ins) {
- case CAC_UPDATE_BUFFER:
- *response = vcard_make_response(
- VCARD7816_STATUS_ERROR_CONDITION_NOT_SATISFIED);
- ret = VCARD_DONE;
- break;
- case CAC_GET_CERTIFICATE:
- if ((apdu->a_p2 != 0) || (apdu->a_p1 != 0)) {
- *response = vcard_make_response(
- VCARD7816_STATUS_ERROR_P1_P2_INCORRECT);
- break;
- }
- assert(pki_applet->cert != NULL);
- size = apdu->a_Le;
- if (pki_applet->cert_buffer == NULL) {
- pki_applet->cert_buffer = pki_applet->cert;
- pki_applet->cert_buffer_len = pki_applet->cert_len;
- }
- size = MIN(size, pki_applet->cert_buffer_len);
- next = MIN(255, pki_applet->cert_buffer_len - size);
- *response = vcard_response_new_bytes(
- card, pki_applet->cert_buffer, size,
- apdu->a_Le, next ?
- VCARD7816_SW1_WARNING_CHANGE :
- VCARD7816_SW1_SUCCESS,
- next);
- pki_applet->cert_buffer += size;
- pki_applet->cert_buffer_len -= size;
- if ((*response == NULL) || (next == 0)) {
- pki_applet->cert_buffer = NULL;
- }
- if (*response == NULL) {
- *response = vcard_make_response(
- VCARD7816_STATUS_EXC_ERROR_MEMORY_FAILURE);
- }
- ret = VCARD_DONE;
- break;
- case CAC_SIGN_DECRYPT:
- if (apdu->a_p2 != 0) {
- *response = vcard_make_response(
- VCARD7816_STATUS_ERROR_P1_P2_INCORRECT);
- break;
- }
- size = apdu->a_Lc;
-
- sign_buffer = g_realloc(pki_applet->sign_buffer,
- pki_applet->sign_buffer_len + size);
- memcpy(sign_buffer+pki_applet->sign_buffer_len, apdu->a_body, size);
- size += pki_applet->sign_buffer_len;
- switch (apdu->a_p1) {
- case 0x80:
- /* p1 == 0x80 means we haven't yet sent the whole buffer, wait for
- * the rest */
- pki_applet->sign_buffer = sign_buffer;
- pki_applet->sign_buffer_len = size;
- *response = vcard_make_response(VCARD7816_STATUS_SUCCESS);
- retain_sign_buffer = TRUE;
- break;
- case 0x00:
- /* we now have the whole buffer, do the operation, result will be
- * in the sign_buffer */
- status = vcard_emul_rsa_op(card, pki_applet->key,
- sign_buffer, size);
- if (status != VCARD7816_STATUS_SUCCESS) {
- *response = vcard_make_response(status);
- break;
- }
- *response = vcard_response_new(card, sign_buffer, size, apdu->a_Le,
- VCARD7816_STATUS_SUCCESS);
- if (*response == NULL) {
- *response = vcard_make_response(
- VCARD7816_STATUS_EXC_ERROR_MEMORY_FAILURE);
- }
- break;
- default:
- *response = vcard_make_response(
- VCARD7816_STATUS_ERROR_P1_P2_INCORRECT);
- break;
- }
- if (!retain_sign_buffer) {
- g_free(sign_buffer);
- pki_applet->sign_buffer = NULL;
- pki_applet->sign_buffer_len = 0;
- }
- ret = VCARD_DONE;
- break;
- case CAC_READ_BUFFER:
- /* new CAC call, go ahead and use the old version for now */
- /* TODO: implement */
- *response = vcard_make_response(
- VCARD7816_STATUS_ERROR_COMMAND_NOT_SUPPORTED);
- ret = VCARD_DONE;
- break;
- default:
- ret = cac_common_process_apdu(card, apdu, response);
- break;
- }
- return ret;
-}
-
-
-static VCardStatus
-cac_applet_id_process_apdu(VCard *card, VCardAPDU *apdu,
- VCardResponse **response)
-{
- VCardStatus ret = VCARD_FAIL;
-
- switch (apdu->a_ins) {
- case CAC_UPDATE_BUFFER:
- *response = vcard_make_response(
- VCARD7816_STATUS_ERROR_CONDITION_NOT_SATISFIED);
- ret = VCARD_DONE;
- break;
- case CAC_READ_BUFFER:
- /* new CAC call, go ahead and use the old version for now */
- /* TODO: implement */
- *response = vcard_make_response(
- VCARD7816_STATUS_ERROR_COMMAND_NOT_SUPPORTED);
- ret = VCARD_DONE;
- break;
- default:
- ret = cac_common_process_apdu(card, apdu, response);
- break;
- }
- return ret;
-}
-
-
-/*
- * TODO: if we ever want to support general CAC middleware, we will need to
- * implement the various containers.
- */
-static VCardStatus
-cac_applet_container_process_apdu(VCard *card, VCardAPDU *apdu,
- VCardResponse **response)
-{
- VCardStatus ret = VCARD_FAIL;
-
- switch (apdu->a_ins) {
- case CAC_READ_BUFFER:
- case CAC_UPDATE_BUFFER:
- *response = vcard_make_response(
- VCARD7816_STATUS_ERROR_COMMAND_NOT_SUPPORTED);
- ret = VCARD_DONE;
- break;
- default:
- ret = cac_common_process_apdu(card, apdu, response);
- break;
- }
- return ret;
-}
-
-/*
- * utilities for creating and destroying the private applet data
- */
-static void
-cac_delete_pki_applet_private(VCardAppletPrivate *applet_private)
-{
- CACPKIAppletData *pki_applet_data;
-
- if (applet_private == NULL) {
- return;
- }
- pki_applet_data = &(applet_private->u.pki_data);
- g_free(pki_applet_data->cert);
- g_free(pki_applet_data->sign_buffer);
- if (pki_applet_data->key != NULL) {
- vcard_emul_delete_key(pki_applet_data->key);
- }
- g_free(applet_private);
-}
-
-static VCardAppletPrivate *
-cac_new_pki_applet_private(const unsigned char *cert,
- int cert_len, VCardKey *key)
-{
- CACPKIAppletData *pki_applet_data;
- VCardAppletPrivate *applet_private;
-
- applet_private = g_new0(VCardAppletPrivate, 1);
- pki_applet_data = &(applet_private->u.pki_data);
- pki_applet_data->cert = (unsigned char *)g_malloc(cert_len+1);
- /*
- * if we want to support compression, then we simply change the 0 to a 1
- * and compress the cert data with libz
- */
- pki_applet_data->cert[0] = 0; /* not compressed */
- memcpy(&pki_applet_data->cert[1], cert, cert_len);
- pki_applet_data->cert_len = cert_len+1;
-
- pki_applet_data->key = key;
- return applet_private;
-}
-
-
-/*
- * create a new cac applet which links to a given cert
- */
-static VCardApplet *
-cac_new_pki_applet(int i, const unsigned char *cert,
- int cert_len, VCardKey *key)
-{
- VCardAppletPrivate *applet_private;
- VCardApplet *applet;
- unsigned char pki_aid[] = { 0xa0, 0x00, 0x00, 0x00, 0x79, 0x01, 0x00 };
- int pki_aid_len = sizeof(pki_aid);
-
- pki_aid[pki_aid_len-1] = i;
-
- applet_private = cac_new_pki_applet_private(cert, cert_len, key);
- if (applet_private == NULL) {
- goto failure;
- }
- applet = vcard_new_applet(cac_applet_pki_process_apdu, cac_applet_pki_reset,
- pki_aid, pki_aid_len);
- if (applet == NULL) {
- goto failure;
- }
- vcard_set_applet_private(applet, applet_private,
- cac_delete_pki_applet_private);
- applet_private = NULL;
-
- return applet;
-
-failure:
- if (applet_private != NULL) {
- cac_delete_pki_applet_private(applet_private);
- }
- return NULL;
-}
-
-
-static unsigned char cac_default_container_aid[] = {
- 0xa0, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00 };
-static unsigned char cac_id_aid[] = {
- 0xa0, 0x00, 0x00, 0x00, 0x79, 0x03, 0x00 };
-/*
- * Initialize the cac card. This is the only public function in this file. All
- * the rest are connected through function pointers.
- */
-VCardStatus
-cac_card_init(VReader *reader, VCard *card,
- const char *params,
- unsigned char * const *cert,
- int cert_len[],
- VCardKey *key[] /* adopt the keys*/,
- int cert_count)
-{
- int i;
- VCardApplet *applet;
-
- /* CAC Cards are VM Cards */
- vcard_set_type(card, VCARD_VM);
-
- /* create one PKI applet for each cert */
- for (i = 0; i < cert_count; i++) {
- applet = cac_new_pki_applet(i, cert[i], cert_len[i], key[i]);
- if (applet == NULL) {
- goto failure;
- }
- vcard_add_applet(card, applet);
- }
-
- /* create a default blank container applet */
- applet = vcard_new_applet(cac_applet_container_process_apdu,
- NULL, cac_default_container_aid,
- sizeof(cac_default_container_aid));
- if (applet == NULL) {
- goto failure;
- }
- vcard_add_applet(card, applet);
-
- /* create a default blank container applet */
- applet = vcard_new_applet(cac_applet_id_process_apdu,
- NULL, cac_id_aid,
- sizeof(cac_id_aid));
- if (applet == NULL) {
- goto failure;
- }
- vcard_add_applet(card, applet);
- return VCARD_DONE;
-
-failure:
- return VCARD_FAIL;
-}
-
diff --git a/libcacard/cac.h b/libcacard/cac.h
deleted file mode 100644
index d24a2a846a..0000000000
--- a/libcacard/cac.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * defines the entry point for the cac card. Only used by cac.c anc
- * vcard_emul_type.c
- *
- * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
- * See the COPYING.LIB file in the top-level directory.
- */
-#ifndef CAC_H
-#define CAC_H 1
-#include "vcard.h"
-#include "vreader.h"
-
-#define CAC_GET_PROPERTIES 0x56
-#define CAC_GET_ACR 0x4c
-#define CAC_READ_BUFFER 0x52
-#define CAC_UPDATE_BUFFER 0x58
-#define CAC_SIGN_DECRYPT 0x42
-#define CAC_GET_CERTIFICATE 0x36
-
-/*
- * Initialize the cac card. This is the only public function in this file. All
- * the rest are connected through function pointers.
- */
-VCardStatus cac_card_init(VReader *reader, VCard *card, const char *params,
- unsigned char * const *cert, int cert_len[],
- VCardKey *key[] /* adopt the keys*/,
- int cert_count);
-
-/* not yet implemented */
-VCardStatus cac_is_cac_card(VReader *reader);
-#endif
diff --git a/libcacard/card_7816.c b/libcacard/card_7816.c
deleted file mode 100644
index 22fd334d15..0000000000
--- a/libcacard/card_7816.c
+++ /dev/null
@@ -1,757 +0,0 @@
-/*
- * Implement the 7816 portion of the card spec
- *
- * This code is licensed under the GNU LGPL, version 2.1 or later.
- * See the COPYING.LIB file in the top-level directory.
- */
-
-#include "glib-compat.h"
-
-#include <string.h>
-
-#include "vcard.h"
-#include "vcard_emul.h"
-#include "card_7816.h"
-
-/*
- * set the status bytes based on the status word
- */
-static void
-vcard_response_set_status(VCardResponse *response, vcard_7816_status_t status)
-{
- unsigned char sw1, sw2;
- response->b_status = status; /* make sure the status and swX representations
- * are consistent */
- sw1 = (status >> 8) & 0xff;
- sw2 = status & 0xff;
- response->b_sw1 = sw1;
- response->b_sw2 = sw2;
- response->b_data[response->b_len] = sw1;
- response->b_data[response->b_len+1] = sw2;
-}
-
-/*
- * set the status bytes in a response buffer
- */
-static void
-vcard_response_set_status_bytes(VCardResponse *response,
- unsigned char sw1, unsigned char sw2)
-{
- response->b_status = sw1 << 8 | sw2;
- response->b_sw1 = sw1;
- response->b_sw2 = sw2;
- response->b_data[response->b_len] = sw1;
- response->b_data[response->b_len+1] = sw2;
-}
-
-/*
- * allocate a VCardResponse structure, plus space for the data buffer, and
- * set up everything but the resonse bytes.
- */
-VCardResponse *
-vcard_response_new_data(unsigned char *buf, int len)
-{
- VCardResponse *new_response;
-
- new_response = g_new(VCardResponse, 1);
- new_response->b_data = g_malloc(len + 2);
- memcpy(new_response->b_data, buf, len);
- new_response->b_total_len = len+2;
- new_response->b_len = len;
- new_response->b_type = VCARD_MALLOC;
- return new_response;
-}
-
-static VCardResponse *
-vcard_init_buffer_response(VCard *card, unsigned char *buf, int len)
-{
- VCardResponse *response;
- VCardBufferResponse *buffer_response;
-
- buffer_response = vcard_get_buffer_response(card);
- if (buffer_response) {
- vcard_set_buffer_response(card, NULL);
- vcard_buffer_response_delete(buffer_response);
- }
- buffer_response = vcard_buffer_response_new(buf, len);
- if (buffer_response == NULL) {
- return NULL;
- }
- response = vcard_response_new_status_bytes(VCARD7816_SW1_RESPONSE_BYTES,
- len > 255 ? 0 : len);
- if (response == NULL) {
- return NULL;
- }
- vcard_set_buffer_response(card, buffer_response);
- return response;
-}
-
-/*
- * general buffer to hold results from APDU calls
- */
-VCardResponse *
-vcard_response_new(VCard *card, unsigned char *buf,
- int len, int Le, vcard_7816_status_t status)
-{
- VCardResponse *new_response;
-
- if (len > Le) {
- return vcard_init_buffer_response(card, buf, len);
- }
- new_response = vcard_response_new_data(buf, len);
- if (new_response == NULL) {
- return NULL;
- }
- vcard_response_set_status(new_response, status);
- return new_response;
-}
-
-/*
- * general buffer to hold results from APDU calls
- */
-VCardResponse *
-vcard_response_new_bytes(VCard *card, unsigned char *buf, int len, int Le,
- unsigned char sw1, unsigned char sw2)
-{
- VCardResponse *new_response;
-
- if (len > Le) {
- return vcard_init_buffer_response(card, buf, len);
- }
- new_response = vcard_response_new_data(buf, len);
- if (new_response == NULL) {
- return NULL;
- }
- vcard_response_set_status_bytes(new_response, sw1, sw2);
- return new_response;
-}
-
-/*
- * get a new Response buffer that only has a status.
- */
-static VCardResponse *
-vcard_response_new_status(vcard_7816_status_t status)
-{
- VCardResponse *new_response;
-
- new_response = g_new(VCardResponse, 1);
- new_response->b_data = &new_response->b_sw1;
- new_response->b_len = 0;
- new_response->b_total_len = 2;
- new_response->b_type = VCARD_MALLOC_STRUCT;
- vcard_response_set_status(new_response, status);
- return new_response;
-}
-
-/*
- * same as above, but specify the status as separate bytes
- */
-VCardResponse *
-vcard_response_new_status_bytes(unsigned char sw1, unsigned char sw2)
-{
- VCardResponse *new_response;
-
- new_response = g_new(VCardResponse, 1);
- new_response->b_data = &new_response->b_sw1;
- new_response->b_len = 0;
- new_response->b_total_len = 2;
- new_response->b_type = VCARD_MALLOC_STRUCT;
- vcard_response_set_status_bytes(new_response, sw1, sw2);
- return new_response;
-}
-
-
-/*
- * free the response buffer. The Buffer has a type to handle the buffer
- * allocated in other ways than through malloc.
- */
-void
-vcard_response_delete(VCardResponse *response)
-{
- if (response == NULL) {
- return;
- }
- switch (response->b_type) {
- case VCARD_MALLOC:
- /* everything was malloc'ed */
- g_free(response->b_data);
- g_free(response);
- break;
- case VCARD_MALLOC_DATA:
- /* only the data buffer was malloc'ed */
- g_free(response->b_data);
- break;
- case VCARD_MALLOC_STRUCT:
- /* only the structure was malloc'ed */
- g_free(response);
- break;
- case VCARD_STATIC:
- break;
- }
-}
-
-/*
- * decode the class bit and set our generic type field, channel, and
- * secure messaging values.
- */
-static vcard_7816_status_t
-vcard_apdu_set_class(VCardAPDU *apdu) {
- apdu->a_channel = 0;
- apdu->a_secure_messaging = 0;
- apdu->a_type = apdu->a_cla & 0xf0;
- apdu->a_gen_type = VCARD_7816_ISO;
-
- /* parse the class tables 8 & 9 of the 7816-4 Part 4 spec */
- switch (apdu->a_type) {
- /* we only support the basic types */
- case 0x00:
- case 0x80:
- case 0x90:
- case 0xa0:
- apdu->a_channel = apdu->a_cla & 3;
- apdu->a_secure_messaging = apdu->a_cla & 0xe;
- break;
- case 0xb0:
- case 0xc0:
- break;
-
- case 0x10:
- case 0x20:
- case 0x30:
- case 0x40:
- case 0x50:
- case 0x60:
- case 0x70:
- /* Reserved for future use */
- apdu->a_gen_type = VCARD_7816_RFU;
- break;
- case 0xd0:
- case 0xe0:
- case 0xf0:
- default:
- apdu->a_gen_type =
- (apdu->a_cla == 0xff) ? VCARD_7816_PTS : VCARD_7816_PROPRIETARY;
- break;
- }
- return VCARD7816_STATUS_SUCCESS;
-}
-
-/*
- * set the Le and Lc fields according to table 5 of the
- * 7816-4 part 4 spec
- */
-static vcard_7816_status_t
-vcard_apdu_set_length(VCardAPDU *apdu)
-{
- int L, Le;
-
- /* process according to table 5 of the 7816-4 Part 4 spec.
- * variable names match the variables in the spec */
- L = apdu->a_len-4; /* fixed APDU header */
- apdu->a_Lc = 0;
- apdu->a_Le = 0;
- apdu->a_body = NULL;
- switch (L) {
- case 0:
- /* 1 minimal apdu */
- return VCARD7816_STATUS_SUCCESS;
- case 1:
- /* 2S only return values apdu */
- /* zero maps to 256 here */
- apdu->a_Le = apdu->a_header->ah_Le ?
- apdu->a_header->ah_Le : 256;
- return VCARD7816_STATUS_SUCCESS;
- default:
- /* if the ah_Le byte is zero and we have more than
- * 1 byte in the header, then we must be using extended Le and Lc.
- * process the extended now. */
- if (apdu->a_header->ah_Le == 0) {
- if (L < 3) {
- /* coding error, need at least 3 bytes */
- return VCARD7816_STATUS_ERROR_WRONG_LENGTH;
- }
- /* calculate the first extended value. Could be either Le or Lc */
- Le = (apdu->a_header->ah_body[0] << 8)
- || apdu->a_header->ah_body[1];
- if (L == 3) {
- /* 2E extended, return data only */
- /* zero maps to 65536 */
- apdu->a_Le = Le ? Le : 65536;
- return VCARD7816_STATUS_SUCCESS;
- }
- if (Le == 0) {
- /* reserved for future use, probably for next time we need
- * to extend the lengths */
- return VCARD7816_STATUS_ERROR_WRONG_LENGTH;
- }
- /* we know that the first extended value is Lc now */
- apdu->a_Lc = Le;
- apdu->a_body = &apdu->a_header->ah_body[2];
- if (L == Le+3) {
- /* 3E extended, only body parameters */
- return VCARD7816_STATUS_SUCCESS;
- }
- if (L == Le+5) {
- /* 4E extended, parameters and return data */
- Le = (apdu->a_data[apdu->a_len-2] << 8)
- || apdu->a_data[apdu->a_len-1];
- apdu->a_Le = Le ? Le : 65536;
- return VCARD7816_STATUS_SUCCESS;
- }
- return VCARD7816_STATUS_ERROR_WRONG_LENGTH;
- }
- /* not extended */
- apdu->a_Lc = apdu->a_header->ah_Le;
- apdu->a_body = &apdu->a_header->ah_body[0];
- if (L == apdu->a_Lc + 1) {
- /* 3S only body parameters */
- return VCARD7816_STATUS_SUCCESS;
- }
- if (L == apdu->a_Lc + 2) {
- /* 4S parameters and return data */
- Le = apdu->a_data[apdu->a_len-1];
- apdu->a_Le = Le ? Le : 256;
- return VCARD7816_STATUS_SUCCESS;
- }
- break;
- }
- return VCARD7816_STATUS_ERROR_WRONG_LENGTH;
-}
-
-/*
- * create a new APDU from a raw set of bytes. This will decode all the
- * above fields. users of VCARDAPDU's can then depend on the already decoded
- * values.
- */
-VCardAPDU *
-vcard_apdu_new(unsigned char *raw_apdu, int len, vcard_7816_status_t *status)
-{
- VCardAPDU *new_apdu;
-
- *status = VCARD7816_STATUS_EXC_ERROR_MEMORY_FAILURE;
- if (len < 4) {
- *status = VCARD7816_STATUS_ERROR_WRONG_LENGTH;
- return NULL;
- }
-
- new_apdu = g_new(VCardAPDU, 1);
- new_apdu->a_data = g_memdup(raw_apdu, len);
- new_apdu->a_len = len;
- *status = vcard_apdu_set_class(new_apdu);
- if (*status != VCARD7816_STATUS_SUCCESS) {
- g_free(new_apdu);
- return NULL;
- }
- *status = vcard_apdu_set_length(new_apdu);
- if (*status != VCARD7816_STATUS_SUCCESS) {
- g_free(new_apdu);
- new_apdu = NULL;
- }
- return new_apdu;
-}
-
-void
-vcard_apdu_delete(VCardAPDU *apdu)
-{
- if (apdu == NULL) {
- return;
- }
- g_free(apdu->a_data);
- g_free(apdu);
-}
-
-
-/*
- * declare response buffers for all the 7816 defined error codes
- */
-VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_SUCCESS)
-VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_WARNING)
-VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_WARNING_RET_CORUPT)
-VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_WARNING_BUF_END_BEFORE_LE)
-VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_WARNING_INVALID_FILE_SELECTED)
-VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_WARNING_FCI_FORMAT_INVALID)
-VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_WARNING_CHANGE)
-VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_WARNING_FILE_FILLED)
-VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_EXC_ERROR)
-VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_EXC_ERROR_CHANGE)
-VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_EXC_ERROR_MEMORY_FAILURE)
-VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_WRONG_LENGTH)
-VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_CLA_NOT_SUPPORTED)
-VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_CHANNEL_NOT_SUPPORTED)
-VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_SECURE_NOT_SUPPORTED)
-VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_COMMAND_NOT_SUPPORTED)
-VCARD_RESPONSE_NEW_STATIC_STATUS(
- VCARD7816_STATUS_ERROR_COMMAND_INCOMPATIBLE_WITH_FILE)
-VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_SECURITY_NOT_SATISFIED)
-VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_AUTHENTICATION_BLOCKED)
-VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_DATA_INVALID)
-VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_CONDITION_NOT_SATISFIED)
-VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_DATA_NO_EF)
-VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_SM_OBJECT_MISSING)
-VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_SM_OBJECT_INCORRECT)
-VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_WRONG_PARAMETERS)
-VCARD_RESPONSE_NEW_STATIC_STATUS(
- VCARD7816_STATUS_ERROR_WRONG_PARAMETERS_IN_DATA)
-VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_FUNCTION_NOT_SUPPORTED)
-VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_FILE_NOT_FOUND)
-VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_RECORD_NOT_FOUND)
-VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_NO_SPACE_FOR_FILE)
-VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_LC_TLV_INCONSISTENT)
-VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_P1_P2_INCORRECT)
-VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_LC_P1_P2_INCONSISTENT)
-VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_DATA_NOT_FOUND)
-VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_WRONG_PARAMETERS_2)
-VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_INS_CODE_INVALID)
-VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_CLA_INVALID)
-VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_GENERAL)
-
-/*
- * return a single response code. This function cannot fail. It will always
- * return a response.
- */
-VCardResponse *
-vcard_make_response(vcard_7816_status_t status)
-{
- VCardResponse *response;
-
- switch (status) {
- /* known 7816 response codes */
- case VCARD7816_STATUS_SUCCESS:
- return VCARD_RESPONSE_GET_STATIC(
- VCARD7816_STATUS_SUCCESS);
- case VCARD7816_STATUS_WARNING:
- return VCARD_RESPONSE_GET_STATIC(
- VCARD7816_STATUS_WARNING);
- case VCARD7816_STATUS_WARNING_RET_CORUPT:
- return VCARD_RESPONSE_GET_STATIC(
- VCARD7816_STATUS_WARNING_RET_CORUPT);
- case VCARD7816_STATUS_WARNING_BUF_END_BEFORE_LE:
- return VCARD_RESPONSE_GET_STATIC(
- VCARD7816_STATUS_WARNING_BUF_END_BEFORE_LE);
- case VCARD7816_STATUS_WARNING_INVALID_FILE_SELECTED:
- return VCARD_RESPONSE_GET_STATIC(
- VCARD7816_STATUS_WARNING_INVALID_FILE_SELECTED);
- case VCARD7816_STATUS_WARNING_FCI_FORMAT_INVALID:
- return VCARD_RESPONSE_GET_STATIC(
- VCARD7816_STATUS_WARNING_FCI_FORMAT_INVALID);
- case VCARD7816_STATUS_WARNING_CHANGE:
- return VCARD_RESPONSE_GET_STATIC(
- VCARD7816_STATUS_WARNING_CHANGE);
- case VCARD7816_STATUS_WARNING_FILE_FILLED:
- return VCARD_RESPONSE_GET_STATIC(
- VCARD7816_STATUS_WARNING_FILE_FILLED);
- case VCARD7816_STATUS_EXC_ERROR:
- return VCARD_RESPONSE_GET_STATIC(
- VCARD7816_STATUS_EXC_ERROR);
- case VCARD7816_STATUS_EXC_ERROR_CHANGE:
- return VCARD_RESPONSE_GET_STATIC(
- VCARD7816_STATUS_EXC_ERROR_CHANGE);
- case VCARD7816_STATUS_EXC_ERROR_MEMORY_FAILURE:
- return VCARD_RESPONSE_GET_STATIC(
- VCARD7816_STATUS_EXC_ERROR_MEMORY_FAILURE);
- case VCARD7816_STATUS_ERROR_WRONG_LENGTH:
- return VCARD_RESPONSE_GET_STATIC(
- VCARD7816_STATUS_ERROR_WRONG_LENGTH);
- case VCARD7816_STATUS_ERROR_CLA_NOT_SUPPORTED:
- return VCARD_RESPONSE_GET_STATIC(
- VCARD7816_STATUS_ERROR_CLA_NOT_SUPPORTED);
- case VCARD7816_STATUS_ERROR_CHANNEL_NOT_SUPPORTED:
- return VCARD_RESPONSE_GET_STATIC(
- VCARD7816_STATUS_ERROR_CHANNEL_NOT_SUPPORTED);
- case VCARD7816_STATUS_ERROR_SECURE_NOT_SUPPORTED:
- return VCARD_RESPONSE_GET_STATIC(
- VCARD7816_STATUS_ERROR_SECURE_NOT_SUPPORTED);
- case VCARD7816_STATUS_ERROR_COMMAND_NOT_SUPPORTED:
- return VCARD_RESPONSE_GET_STATIC(
- VCARD7816_STATUS_ERROR_COMMAND_NOT_SUPPORTED);
- case VCARD7816_STATUS_ERROR_COMMAND_INCOMPATIBLE_WITH_FILE:
- return VCARD_RESPONSE_GET_STATIC(
- VCARD7816_STATUS_ERROR_COMMAND_INCOMPATIBLE_WITH_FILE);
- case VCARD7816_STATUS_ERROR_SECURITY_NOT_SATISFIED:
- return VCARD_RESPONSE_GET_STATIC(
- VCARD7816_STATUS_ERROR_SECURITY_NOT_SATISFIED);
- case VCARD7816_STATUS_ERROR_AUTHENTICATION_BLOCKED:
- return VCARD_RESPONSE_GET_STATIC(
- VCARD7816_STATUS_ERROR_AUTHENTICATION_BLOCKED);
- case VCARD7816_STATUS_ERROR_DATA_INVALID:
- return VCARD_RESPONSE_GET_STATIC(
- VCARD7816_STATUS_ERROR_DATA_INVALID);
- case VCARD7816_STATUS_ERROR_CONDITION_NOT_SATISFIED:
- return VCARD_RESPONSE_GET_STATIC(
- VCARD7816_STATUS_ERROR_CONDITION_NOT_SATISFIED);
- case VCARD7816_STATUS_ERROR_DATA_NO_EF:
- return VCARD_RESPONSE_GET_STATIC(
- VCARD7816_STATUS_ERROR_DATA_NO_EF);
- case VCARD7816_STATUS_ERROR_SM_OBJECT_MISSING:
- return VCARD_RESPONSE_GET_STATIC(
- VCARD7816_STATUS_ERROR_SM_OBJECT_MISSING);
- case VCARD7816_STATUS_ERROR_SM_OBJECT_INCORRECT:
- return VCARD_RESPONSE_GET_STATIC(
- VCARD7816_STATUS_ERROR_SM_OBJECT_INCORRECT);
- case VCARD7816_STATUS_ERROR_WRONG_PARAMETERS:
- return VCARD_RESPONSE_GET_STATIC(
- VCARD7816_STATUS_ERROR_WRONG_PARAMETERS);
- case VCARD7816_STATUS_ERROR_WRONG_PARAMETERS_IN_DATA:
- return VCARD_RESPONSE_GET_STATIC(
- VCARD7816_STATUS_ERROR_WRONG_PARAMETERS_IN_DATA);
- case VCARD7816_STATUS_ERROR_FUNCTION_NOT_SUPPORTED:
- return VCARD_RESPONSE_GET_STATIC(
- VCARD7816_STATUS_ERROR_FUNCTION_NOT_SUPPORTED);
- case VCARD7816_STATUS_ERROR_FILE_NOT_FOUND:
- return VCARD_RESPONSE_GET_STATIC(
- VCARD7816_STATUS_ERROR_FILE_NOT_FOUND);
- case VCARD7816_STATUS_ERROR_RECORD_NOT_FOUND:
- return VCARD_RESPONSE_GET_STATIC(
- VCARD7816_STATUS_ERROR_RECORD_NOT_FOUND);
- case VCARD7816_STATUS_ERROR_NO_SPACE_FOR_FILE:
- return VCARD_RESPONSE_GET_STATIC(
- VCARD7816_STATUS_ERROR_NO_SPACE_FOR_FILE);
- case VCARD7816_STATUS_ERROR_LC_TLV_INCONSISTENT:
- return VCARD_RESPONSE_GET_STATIC(
- VCARD7816_STATUS_ERROR_LC_TLV_INCONSISTENT);
- case VCARD7816_STATUS_ERROR_P1_P2_INCORRECT:
- return VCARD_RESPONSE_GET_STATIC(
- VCARD7816_STATUS_ERROR_P1_P2_INCORRECT);
- case VCARD7816_STATUS_ERROR_LC_P1_P2_INCONSISTENT:
- return VCARD_RESPONSE_GET_STATIC(
- VCARD7816_STATUS_ERROR_LC_P1_P2_INCONSISTENT);
- case VCARD7816_STATUS_ERROR_DATA_NOT_FOUND:
- return VCARD_RESPONSE_GET_STATIC(
- VCARD7816_STATUS_ERROR_DATA_NOT_FOUND);
- case VCARD7816_STATUS_ERROR_WRONG_PARAMETERS_2:
- return VCARD_RESPONSE_GET_STATIC(
- VCARD7816_STATUS_ERROR_WRONG_PARAMETERS_2);
- case VCARD7816_STATUS_ERROR_INS_CODE_INVALID:
- return VCARD_RESPONSE_GET_STATIC(
- VCARD7816_STATUS_ERROR_INS_CODE_INVALID);
- case VCARD7816_STATUS_ERROR_CLA_INVALID:
- return VCARD_RESPONSE_GET_STATIC(
- VCARD7816_STATUS_ERROR_CLA_INVALID);
- case VCARD7816_STATUS_ERROR_GENERAL:
- return VCARD_RESPONSE_GET_STATIC(
- VCARD7816_STATUS_ERROR_GENERAL);
- default:
- /* we don't know this status code, create a response buffer to
- * hold it */
- response = vcard_response_new_status(status);
- if (response == NULL) {
- /* couldn't allocate the buffer, return memmory error */
- return VCARD_RESPONSE_GET_STATIC(
- VCARD7816_STATUS_EXC_ERROR_MEMORY_FAILURE);
- }
- return response;
- }
-}
-
-/*
- * Add File card support here if you need it.
- */
-static VCardStatus
-vcard7816_file_system_process_apdu(VCard *card, VCardAPDU *apdu,
- VCardResponse **response)
-{
- /* TODO: if we want to support a virtual file system card, we do it here.
- * It would probably be a pkcs #15 card type */
- *response = vcard_make_response(
- VCARD7816_STATUS_ERROR_COMMAND_NOT_SUPPORTED);
- return VCARD_DONE;
-}
-
-/*
- * VM card (including java cards)
- */
-static VCardStatus
-vcard7816_vm_process_apdu(VCard *card, VCardAPDU *apdu,
- VCardResponse **response)
-{
- int bytes_to_copy, next_byte_count, count;
- VCardApplet *current_applet;
- VCardBufferResponse *buffer_response;
- vcard_7816_status_t status;
-
- /* parse the class first */
- if (apdu->a_gen_type != VCARD_7816_ISO) {
- *response = vcard_make_response(
- VCARD7816_STATUS_ERROR_COMMAND_NOT_SUPPORTED);
- return VCARD_DONE;
- }
-
- /* use a switch so that if we need to support secure channel stuff later,
- * we know where to put it */
- switch (apdu->a_secure_messaging) {
- case 0x0: /* no SM */
- break;
- case 0x4: /* proprietary SM */
- case 0x8: /* header not authenticated */
- case 0xc: /* header authenticated */
- default:
- /* for now, don't try to support secure channel stuff in the
- * virtual card. */
- *response = vcard_make_response(
- VCARD7816_STATUS_ERROR_SECURE_NOT_SUPPORTED);
- return VCARD_DONE;
- }
-
- /* now parse the instruction */
- switch (apdu->a_ins) {
- case VCARD7816_INS_MANAGE_CHANNEL: /* secure channel op */
- case VCARD7816_INS_EXTERNAL_AUTHENTICATE: /* secure channel op */
- case VCARD7816_INS_GET_CHALLENGE: /* secure channel op */
- case VCARD7816_INS_INTERNAL_AUTHENTICATE: /* secure channel op */
- case VCARD7816_INS_ERASE_BINARY: /* applet control op */
- case VCARD7816_INS_READ_BINARY: /* applet control op */
- case VCARD7816_INS_WRITE_BINARY: /* applet control op */
- case VCARD7816_INS_UPDATE_BINARY: /* applet control op */
- case VCARD7816_INS_READ_RECORD: /* file op */
- case VCARD7816_INS_WRITE_RECORD: /* file op */
- case VCARD7816_INS_UPDATE_RECORD: /* file op */
- case VCARD7816_INS_APPEND_RECORD: /* file op */
- case VCARD7816_INS_ENVELOPE:
- case VCARD7816_INS_PUT_DATA:
- *response = vcard_make_response(
- VCARD7816_STATUS_ERROR_COMMAND_NOT_SUPPORTED);
- break;
-
- case VCARD7816_INS_SELECT_FILE:
- if (apdu->a_p1 != 0x04) {
- *response = vcard_make_response(
- VCARD7816_STATUS_ERROR_FUNCTION_NOT_SUPPORTED);
- break;
- }
-
- /* side effect, deselect the current applet if no applet has been found
- * */
- current_applet = vcard_find_applet(card, apdu->a_body, apdu->a_Lc);
- vcard_select_applet(card, apdu->a_channel, current_applet);
- if (current_applet) {
- unsigned char *aid;
- int aid_len;
- aid = vcard_applet_get_aid(current_applet, &aid_len);
- *response = vcard_response_new(card, aid, aid_len, apdu->a_Le,
- VCARD7816_STATUS_SUCCESS);
- } else {
- *response = vcard_make_response(
- VCARD7816_STATUS_ERROR_FILE_NOT_FOUND);
- }
- break;
-
- case VCARD7816_INS_VERIFY:
- if ((apdu->a_p1 != 0x00) || (apdu->a_p2 != 0x00)) {
- *response = vcard_make_response(
- VCARD7816_STATUS_ERROR_WRONG_PARAMETERS);
- } else {
- if (apdu->a_Lc == 0) {
- /* handle pin count if possible */
- count = vcard_emul_get_login_count(card);
- if (count < 0) {
- *response = vcard_make_response(
- VCARD7816_STATUS_ERROR_DATA_NOT_FOUND);
- } else {
- if (count > 0xf) {
- count = 0xf;
- }
- *response = vcard_response_new_status_bytes(
- VCARD7816_SW1_WARNING_CHANGE,
- 0xc0 | count);
- if (*response == NULL) {
- *response = vcard_make_response(
- VCARD7816_STATUS_EXC_ERROR_MEMORY_FAILURE);
- }
- }
- } else {
- status = vcard_emul_login(card, apdu->a_body, apdu->a_Lc);
- *response = vcard_make_response(status);
- }
- }
- break;
-
- case VCARD7816_INS_GET_RESPONSE:
- buffer_response = vcard_get_buffer_response(card);
- if (!buffer_response) {
- *response = vcard_make_response(
- VCARD7816_STATUS_ERROR_DATA_NOT_FOUND);
- /* handle error */
- break;
- }
- bytes_to_copy = MIN(buffer_response->len, apdu->a_Le);
- next_byte_count = MIN(256, buffer_response->len - bytes_to_copy);
- *response = vcard_response_new_bytes(
- card, buffer_response->current, bytes_to_copy,
- apdu->a_Le,
- next_byte_count ?
- VCARD7816_SW1_RESPONSE_BYTES : VCARD7816_SW1_SUCCESS,
- next_byte_count);
- buffer_response->current += bytes_to_copy;
- buffer_response->len -= bytes_to_copy;
- if (*response == NULL || (next_byte_count == 0)) {
- vcard_set_buffer_response(card, NULL);
- vcard_buffer_response_delete(buffer_response);
- }
- if (*response == NULL) {
- *response =
- vcard_make_response(VCARD7816_STATUS_EXC_ERROR_MEMORY_FAILURE);
- }
- break;
-
- case VCARD7816_INS_GET_DATA:
- *response =
- vcard_make_response(VCARD7816_STATUS_ERROR_COMMAND_NOT_SUPPORTED);
- break;
-
- default:
- *response =
- vcard_make_response(VCARD7816_STATUS_ERROR_COMMAND_NOT_SUPPORTED);
- break;
- }
-
- /* response should have been set somewhere */
- assert(*response != NULL);
- return VCARD_DONE;
-}
-
-
-/*
- * APDU processing starts here. This routes the card processing stuff to the
- * right location.
- */
-VCardStatus
-vcard_process_apdu(VCard *card, VCardAPDU *apdu, VCardResponse **response)
-{
- VCardStatus status;
- VCardBufferResponse *buffer_response;
-
- /* first handle any PTS commands, which aren't really APDU's */
- if (apdu->a_type == VCARD_7816_PTS) {
- /* the PTS responses aren't really responses either */
- *response = vcard_response_new_data(apdu->a_data, apdu->a_len);
- /* PTS responses have no status bytes */
- (*response)->b_total_len = (*response)->b_len;
- return VCARD_DONE;
- }
- buffer_response = vcard_get_buffer_response(card);
- if (buffer_response && apdu->a_ins != VCARD7816_INS_GET_RESPONSE) {
- /* clear out buffer_response, return an error */
- vcard_set_buffer_response(card, NULL);
- vcard_buffer_response_delete(buffer_response);
- *response = vcard_make_response(VCARD7816_STATUS_EXC_ERROR);
- return VCARD_DONE;
- }
-
- status = vcard_process_applet_apdu(card, apdu, response);
- if (status != VCARD_NEXT) {
- return status;
- }
- switch (vcard_get_type(card)) {
- case VCARD_FILE_SYSTEM:
- return vcard7816_file_system_process_apdu(card, apdu, response);
- case VCARD_VM:
- return vcard7816_vm_process_apdu(card, apdu, response);
- case VCARD_DIRECT:
- /* if we are type direct, then the applet should handle everything */
- assert(!"VCARD_DIRECT: applet failure");
- break;
- }
- *response =
- vcard_make_response(VCARD7816_STATUS_ERROR_COMMAND_NOT_SUPPORTED);
- return VCARD_DONE;
-}
diff --git a/libcacard/card_7816.h b/libcacard/card_7816.h
deleted file mode 100644
index 4a01993d2d..0000000000
--- a/libcacard/card_7816.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Implement the 7816 portion of the card spec
- *
- * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
- * See the COPYING.LIB file in the top-level directory.
- */
-#ifndef CARD_7816_H
-#define CARD_7816_H 1
-
-#include "card_7816t.h"
-#include "vcardt.h"
-
-/*
- * constructors for VCardResponse's
- */
-/* response from a return buffer and a status */
-VCardResponse *vcard_response_new(VCard *card, unsigned char *buf, int len,
- int Le, vcard_7816_status_t status);
-/* response from a return buffer and status bytes */
-VCardResponse *vcard_response_new_bytes(VCard *card, unsigned char *buf,
- int len, int Le,
- unsigned char sw1, unsigned char sw2);
-/* response from just status bytes */
-VCardResponse *vcard_response_new_status_bytes(unsigned char sw1,
- unsigned char sw2);
-/* response from just status: NOTE this cannot fail, it will always return a
- * valid response, if it can't allocate memory, the response will be
- * VCARD7816_STATUS_EXC_ERROR_MEMORY_FAILURE */
-VCardResponse *vcard_make_response(vcard_7816_status_t status);
-
-/* create a raw response (status has already been encoded */
-VCardResponse *vcard_response_new_data(unsigned char *buf, int len);
-
-
-
-
-/*
- * destructor for VCardResponse.
- * Can be called with a NULL response
- */
-void vcard_response_delete(VCardResponse *response);
-
-/*
- * constructor for VCardAPDU
- */
-VCardAPDU *vcard_apdu_new(unsigned char *raw_apdu, int len,
- unsigned short *status);
-
-/*
- * destructor for VCardAPDU
- * Can be called with a NULL apdu
- */
-void vcard_apdu_delete(VCardAPDU *apdu);
-
-/*
- * APDU processing starts here. This routes the card processing stuff to the
- * right location. Always returns a valid response.
- */
-VCardStatus vcard_process_apdu(VCard *card, VCardAPDU *apdu,
- VCardResponse **response);
-
-#endif
diff --git a/libcacard/card_7816t.h b/libcacard/card_7816t.h
deleted file mode 100644
index 386acc5dc0..0000000000
--- a/libcacard/card_7816t.h
+++ /dev/null
@@ -1,165 +0,0 @@
-/*
- * Implement the 7816 portion of the card spec
- *
- * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
- * See the COPYING.LIB file in the top-level directory.
- */
-#ifndef CARD_7816T_H
-#define CARD_7816T_H 1
-
-typedef unsigned short vcard_7816_status_t;
-
-struct VCardResponseStruct {
- unsigned char *b_data;
- vcard_7816_status_t b_status;
- unsigned char b_sw1;
- unsigned char b_sw2;
- int b_len;
- int b_total_len;
- enum VCardResponseBufferType {
- VCARD_MALLOC,
- VCARD_MALLOC_DATA,
- VCARD_MALLOC_STRUCT,
- VCARD_STATIC
- } b_type;
-};
-
-#define VCARD_RESPONSE_NEW_STATIC_STATUS(stat) \
-static const VCardResponse VCardResponse##stat = \
- {(unsigned char *)&VCardResponse##stat.b_sw1, (stat), ((stat) >> 8), \
- ((stat) & 0xff), 0, 2, VCARD_STATIC};
-
-#define VCARD_RESPONSE_NEW_STATIC_STATUS_BYTES(sw1, sw2) \
-static const VCardResponse VCARDResponse##sw1 = \
- {(unsigned char *)&VCardResponse##name.b_sw1, ((sw1) << 8 | (sw2)), \
- (sw1), (sw2), 0, 2, VCARD_STATIC};
-
-/* cast away the const, callers need may need to 'free' the
- * result, and const implies that they don't */
-#define VCARD_RESPONSE_GET_STATIC(name) \
- ((VCardResponse *)(&VCardResponse##name))
-
-typedef enum {
- VCARD_7816_ISO,
- VCARD_7816_RFU,
- VCARD_7816_PTS,
- VCARD_7816_PROPRIETARY
-} VCardAPDUType;
-
-
-/*
- * 7816 header. All APDU's have this header.
- * They must be laid out in this order.
- */
-struct VCardAPDUHeader {
- unsigned char ah_cla;
- unsigned char ah_ins;
- unsigned char ah_p1;
- unsigned char ah_p2;
- unsigned char ah_Le;
- unsigned char ah_body[1]; /* indefinite length */
-};
-
-/*
- * 7816 APDU structure. The raw bytes are stored in the union and can be
- * accessed directly through u.data (which is aliased as a_data).
- *
- * Names of the fields match the 7816 documentation.
- */
-struct VCardAPDUStruct {
- int a_len; /* length of the whole buffer, including header */
- int a_Lc; /* 7816 Lc (parameter length) value */
- int a_Le; /* 7816 Le (expected result length) value */
- unsigned char *a_body; /* pointer to the parameter */
- int a_channel; /* decoded channel */
- int a_secure_messaging; /* decoded secure messaging type */
- int a_type; /* decoded type from cla (top nibble of class) */
- VCardAPDUType a_gen_type; /* generic type (7816, PROPRIETARY, RFU, etc) */
- union {
- struct VCardAPDUHeader *header;
- unsigned char *data;
- } u;
-/* give the subfields a unified look */
-#define a_header u.header
-#define a_data u.data
-#define a_cla a_header->ah_cla /* class */
-#define a_ins a_header->ah_ins /* instruction */
-#define a_p1 a_header->ah_p1 /* parameter 1 */
-#define a_p2 a_header->ah_p2 /* parameter 2 */
-};
-
-/* 7816 status codes */
-#define VCARD7816_STATUS_SUCCESS 0x9000
-#define VCARD7816_STATUS_WARNING 0x6200
-#define VCARD7816_STATUS_WARNING_RET_CORUPT 0x6281
-#define VCARD7816_STATUS_WARNING_BUF_END_BEFORE_LE 0x6282
-#define VCARD7816_STATUS_WARNING_INVALID_FILE_SELECTED 0x6283
-#define VCARD7816_STATUS_WARNING_FCI_FORMAT_INVALID 0x6284
-#define VCARD7816_STATUS_WARNING_CHANGE 0x6300
-#define VCARD7816_STATUS_WARNING_FILE_FILLED 0x6381
-#define VCARD7816_STATUS_EXC_ERROR 0x6400
-#define VCARD7816_STATUS_EXC_ERROR_CHANGE 0x6500
-#define VCARD7816_STATUS_EXC_ERROR_MEMORY_FAILURE 0x6581
-#define VCARD7816_STATUS_ERROR_WRONG_LENGTH 0x6700
-#define VCARD7816_STATUS_ERROR_CLA_NOT_SUPPORTED 0x6800
-#define VCARD7816_STATUS_ERROR_CHANNEL_NOT_SUPPORTED 0x6881
-#define VCARD7816_STATUS_ERROR_SECURE_NOT_SUPPORTED 0x6882
-#define VCARD7816_STATUS_ERROR_COMMAND_NOT_SUPPORTED 0x6900
-#define VCARD7816_STATUS_ERROR_COMMAND_INCOMPATIBLE_WITH_FILE 0x6981
-#define VCARD7816_STATUS_ERROR_SECURITY_NOT_SATISFIED 0x6982
-#define VCARD7816_STATUS_ERROR_AUTHENTICATION_BLOCKED 0x6983
-#define VCARD7816_STATUS_ERROR_DATA_INVALID 0x6984
-#define VCARD7816_STATUS_ERROR_CONDITION_NOT_SATISFIED 0x6985
-#define VCARD7816_STATUS_ERROR_DATA_NO_EF 0x6986
-#define VCARD7816_STATUS_ERROR_SM_OBJECT_MISSING 0x6987
-#define VCARD7816_STATUS_ERROR_SM_OBJECT_INCORRECT 0x6988
-#define VCARD7816_STATUS_ERROR_WRONG_PARAMETERS 0x6a00
-#define VCARD7816_STATUS_ERROR_WRONG_PARAMETERS_IN_DATA 0x6a80
-#define VCARD7816_STATUS_ERROR_FUNCTION_NOT_SUPPORTED 0x6a81
-#define VCARD7816_STATUS_ERROR_FILE_NOT_FOUND 0x6a82
-#define VCARD7816_STATUS_ERROR_RECORD_NOT_FOUND 0x6a83
-#define VCARD7816_STATUS_ERROR_NO_SPACE_FOR_FILE 0x6a84
-#define VCARD7816_STATUS_ERROR_LC_TLV_INCONSISTENT 0x6a85
-#define VCARD7816_STATUS_ERROR_P1_P2_INCORRECT 0x6a86
-#define VCARD7816_STATUS_ERROR_LC_P1_P2_INCONSISTENT 0x6a87
-#define VCARD7816_STATUS_ERROR_DATA_NOT_FOUND 0x6a88
-#define VCARD7816_STATUS_ERROR_WRONG_PARAMETERS_2 0x6b00
-#define VCARD7816_STATUS_ERROR_INS_CODE_INVALID 0x6d00
-#define VCARD7816_STATUS_ERROR_CLA_INVALID 0x6e00
-#define VCARD7816_STATUS_ERROR_GENERAL 0x6f00
-/* 7816 sw1 codes */
-#define VCARD7816_SW1_SUCCESS 0x90
-#define VCARD7816_SW1_RESPONSE_BYTES 0x61
-#define VCARD7816_SW1_WARNING 0x62
-#define VCARD7816_SW1_WARNING_CHANGE 0x63
-#define VCARD7816_SW1_EXC_ERROR 0x64
-#define VCARD7816_SW1_EXC_ERROR_CHANGE 0x65
-#define VCARD7816_SW1_ERROR_WRONG_LENGTH 0x67
-#define VCARD7816_SW1_CLA_ERROR 0x68
-#define VCARD7816_SW1_COMMAND_ERROR 0x69
-#define VCARD7816_SW1_P1_P2_ERROR 0x6a
-#define VCARD7816_SW1_LE_ERROR 0x6c
-#define VCARD7816_SW1_INS_ERROR 0x6d
-#define VCARD7816_SW1_CLA_NOT_SUPPORTED 0x6e
-
-/* 7816 Instructions */
-#define VCARD7816_INS_MANAGE_CHANNEL 0x70
-#define VCARD7816_INS_EXTERNAL_AUTHENTICATE 0x82
-#define VCARD7816_INS_GET_CHALLENGE 0x84
-#define VCARD7816_INS_INTERNAL_AUTHENTICATE 0x88
-#define VCARD7816_INS_ERASE_BINARY 0x0e
-#define VCARD7816_INS_READ_BINARY 0xb0
-#define VCARD7816_INS_WRITE_BINARY 0xd0
-#define VCARD7816_INS_UPDATE_BINARY 0xd6
-#define VCARD7816_INS_READ_RECORD 0xb2
-#define VCARD7816_INS_WRITE_RECORD 0xd2
-#define VCARD7816_INS_UPDATE_RECORD 0xdc
-#define VCARD7816_INS_APPEND_RECORD 0xe2
-#define VCARD7816_INS_ENVELOPE 0xc2
-#define VCARD7816_INS_PUT_DATA 0xda
-#define VCARD7816_INS_GET_DATA 0xca
-#define VCARD7816_INS_SELECT_FILE 0xa4
-#define VCARD7816_INS_VERIFY 0x20
-#define VCARD7816_INS_GET_RESPONSE 0xc0
-
-#endif
diff --git a/libcacard/event.c b/libcacard/event.c
deleted file mode 100644
index 63f4057fe5..0000000000
--- a/libcacard/event.c
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- * event queue implementation.
- *
- * This code is licensed under the GNU LGPL, version 2.1 or later.
- * See the COPYING.LIB file in the top-level directory.
- */
-
-#include "glib-compat.h"
-
-#include "vcard.h"
-#include "vreader.h"
-#include "vevent.h"
-
-VEvent *
-vevent_new(VEventType type, VReader *reader, VCard *card)
-{
- VEvent *new_vevent;
-
- new_vevent = g_new(VEvent, 1);
- new_vevent->next = NULL;
- new_vevent->type = type;
- new_vevent->reader = vreader_reference(reader);
- new_vevent->card = vcard_reference(card);
-
- return new_vevent;
-}
-
-void
-vevent_delete(VEvent *vevent)
-{
- if (vevent == NULL) {
- return;
- }
- vreader_free(vevent->reader);
- vcard_free(vevent->card);
- g_free(vevent);
-}
-
-/*
- * VEvent queue management
- */
-
-static VEvent *vevent_queue_head;
-static VEvent *vevent_queue_tail;
-static CompatGMutex vevent_queue_lock;
-static CompatGCond vevent_queue_condition;
-
-void vevent_queue_init(void)
-{
- vevent_queue_head = vevent_queue_tail = NULL;
-}
-
-void
-vevent_queue_vevent(VEvent *vevent)
-{
- vevent->next = NULL;
- g_mutex_lock(&vevent_queue_lock);
- if (vevent_queue_head) {
- assert(vevent_queue_tail);
- vevent_queue_tail->next = vevent;
- } else {
- vevent_queue_head = vevent;
- }
- vevent_queue_tail = vevent;
- g_cond_signal(&vevent_queue_condition);
- g_mutex_unlock(&vevent_queue_lock);
-}
-
-/* must have lock */
-static VEvent *
-vevent_dequeue_vevent(void)
-{
- VEvent *vevent = NULL;
- if (vevent_queue_head) {
- vevent = vevent_queue_head;
- vevent_queue_head = vevent->next;
- vevent->next = NULL;
- }
- return vevent;
-}
-
-VEvent *vevent_wait_next_vevent(void)
-{
- VEvent *vevent;
-
- g_mutex_lock(&vevent_queue_lock);
- while ((vevent = vevent_dequeue_vevent()) == NULL) {
- g_cond_wait(&vevent_queue_condition, &vevent_queue_lock);
- }
- g_mutex_unlock(&vevent_queue_lock);
- return vevent;
-}
-
-VEvent *vevent_get_next_vevent(void)
-{
- VEvent *vevent;
-
- g_mutex_lock(&vevent_queue_lock);
- vevent = vevent_dequeue_vevent();
- g_mutex_unlock(&vevent_queue_lock);
- return vevent;
-}
-
diff --git a/libcacard/eventt.h b/libcacard/eventt.h
deleted file mode 100644
index 0dc7bd468c..0000000000
--- a/libcacard/eventt.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
- * See the COPYING.LIB file in the top-level directory.
- */
-
-#ifndef EVENTT_H
-#define EVENTT_H 1
-#include "vreadert.h"
-#include "vcardt.h"
-
-typedef struct VEventStruct VEvent;
-
-typedef enum {
- VEVENT_READER_INSERT,
- VEVENT_READER_REMOVE,
- VEVENT_CARD_INSERT,
- VEVENT_CARD_REMOVE,
- VEVENT_LAST,
-} VEventType;
-
-struct VEventStruct {
- VEvent *next;
- VEventType type;
- VReader *reader;
- VCard *card;
-};
-#endif
-
-
diff --git a/libcacard/libcacard.pc.in b/libcacard/libcacard.pc.in
deleted file mode 100644
index 4b60023ce9..0000000000
--- a/libcacard/libcacard.pc.in
+++ /dev/null
@@ -1,13 +0,0 @@
-prefix=@PREFIX@
-exec_prefix=${prefix}
-libdir=@LIBDIR@
-includedir=@INCLUDEDIR@
-
-Name: cacard
-Description: CA Card library
-Version: @VERSION@
-
-Requires.private: nss glib-2.0
-Libs: -L${libdir} -lcacard
-Libs.private:
-Cflags: -I${includedir}
diff --git a/libcacard/libcacard.syms b/libcacard/libcacard.syms
deleted file mode 100644
index 1697515a7f..0000000000
--- a/libcacard/libcacard.syms
+++ /dev/null
@@ -1,77 +0,0 @@
-cac_card_init
-cac_is_cac_card
-vcard_add_applet
-vcard_apdu_delete
-vcard_apdu_new
-vcard_applet_get_aid
-vcard_buffer_response_delete
-vcard_buffer_response_new
-vcard_delete_applet
-vcard_emul_delete_key
-vcard_emul_force_card_insert
-vcard_emul_force_card_remove
-vcard_emul_get_atr
-vcard_emul_get_login_count
-vcard_emul_init
-vcard_emul_login
-vcard_emul_options
-vcard_emul_replay_insertion_events
-vcard_emul_reset
-vcard_emul_rsa_op
-vcard_emul_type_from_string
-vcard_emul_type_select
-vcard_emul_usage
-vcard_find_applet
-vcard_free
-vcard_get_atr
-vcard_get_buffer_response
-vcard_get_current_applet_private
-vcard_get_private
-vcard_get_type
-vcard_init
-vcard_make_response
-vcard_new
-vcard_new_applet
-vcard_process_apdu
-vcard_process_applet_apdu
-vcard_reference
-vcard_reset
-vcard_response_delete
-vcard_response_new
-vcard_response_new_bytes
-vcard_response_new_data
-vcard_response_new_status_bytes
-vcard_select_applet
-vcard_set_applet_private
-vcard_set_atr_func
-vcard_set_buffer_response
-vcard_set_type
-vevent_delete
-vevent_get_next_vevent
-vevent_new
-vevent_queue_init
-vevent_queue_vevent
-vevent_wait_next_vevent
-vreader_add_reader
-vreader_card_is_present
-vreader_free
-vreader_get_id
-vreader_get_name
-vreader_get_private
-vreader_get_reader_by_id
-vreader_get_reader_by_name
-vreader_get_reader_list
-vreader_init
-vreader_insert_card
-vreader_list_delete
-vreader_list_get_first
-vreader_list_get_next
-vreader_list_get_reader
-vreader_new
-vreader_power_off
-vreader_power_on
-vreader_queue_card_event
-vreader_reference
-vreader_remove_reader
-vreader_set_id
-vreader_xfr_bytes
diff --git a/libcacard/link_test.c b/libcacard/link_test.c
deleted file mode 100644
index 6f67a23d95..0000000000
--- a/libcacard/link_test.c
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
- * See the COPYING.LIB file in the top-level directory.
- */
-
-#include <stdio.h>
-#include "vcard.h"
-
-VCardStatus cac_card_init(const char *flags, VCard *card,
- const unsigned char *cert[],
- int cert_len[], VCardKey *key[] /* adopt the keys*/,
- int cert_count);
-/*
- * this will crash... just test the linkage right now
- */
-
-main(int argc, char **argv)
-{
- VCard *card; /* no constructor yet */
- cac_card_init("", card, NULL, 0, NULL, 0);
-}
-
diff --git a/libcacard/vcard.c b/libcacard/vcard.c
deleted file mode 100644
index 1a87208f3d..0000000000
--- a/libcacard/vcard.c
+++ /dev/null
@@ -1,325 +0,0 @@
-/*
- * implement the Java card standard.
- *
- * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
- * See the COPYING.LIB file in the top-level directory.
- */
-
-#include "glib-compat.h"
-
-#include <string.h>
-
-#include "vcard.h"
-#include "vcard_emul.h"
-#include "card_7816t.h"
-
-struct VCardAppletStruct {
- VCardApplet *next;
- VCardProcessAPDU process_apdu;
- VCardResetApplet reset_applet;
- unsigned char *aid;
- int aid_len;
- void *applet_private;
- VCardAppletPrivateFree applet_private_free;
-};
-
-struct VCardStruct {
- int reference_count;
- VCardApplet *applet_list;
- VCardApplet *current_applet[MAX_CHANNEL];
- VCardBufferResponse *vcard_buffer_response;
- VCardType type;
- VCardEmul *vcard_private;
- VCardEmulFree vcard_private_free;
- VCardGetAtr vcard_get_atr;
-};
-
-VCardBufferResponse *
-vcard_buffer_response_new(unsigned char *buffer, int size)
-{
- VCardBufferResponse *new_buffer;
-
- new_buffer = g_new(VCardBufferResponse, 1);
- new_buffer->buffer = (unsigned char *)g_memdup(buffer, size);
- new_buffer->buffer_len = size;
- new_buffer->current = new_buffer->buffer;
- new_buffer->len = size;
- return new_buffer;
-}
-
-void
-vcard_buffer_response_delete(VCardBufferResponse *buffer_response)
-{
- if (buffer_response == NULL) {
- return;
- }
- g_free(buffer_response->buffer);
- g_free(buffer_response);
-}
-
-
-/*
- * clean up state after a reset
- */
-void
-vcard_reset(VCard *card, VCardPower power)
-{
- int i;
- VCardApplet *applet = NULL;
-
- if (card->type == VCARD_DIRECT) {
- /* select the last applet */
- VCardApplet *current_applet = NULL;
- for (current_applet = card->applet_list; current_applet;
- current_applet = current_applet->next) {
- applet = current_applet;
- }
- }
- for (i = 0; i < MAX_CHANNEL; i++) {
- card->current_applet[i] = applet;
- }
- if (card->vcard_buffer_response) {
- vcard_buffer_response_delete(card->vcard_buffer_response);
- card->vcard_buffer_response = NULL;
- }
- vcard_emul_reset(card, power);
- if (applet) {
- applet->reset_applet(card, 0);
- }
-}
-
-/* applet utilities */
-
-/*
- * applet utilities
- */
-/* constructor */
-VCardApplet *
-vcard_new_applet(VCardProcessAPDU applet_process_function,
- VCardResetApplet applet_reset_function,
- unsigned char *aid, int aid_len)
-{
- VCardApplet *applet;
-
- applet = g_new0(VCardApplet, 1);
- applet->process_apdu = applet_process_function;
- applet->reset_applet = applet_reset_function;
-
- applet->aid = g_memdup(aid, aid_len);
- applet->aid_len = aid_len;
- return applet;
-}
-
-/* destructor */
-void
-vcard_delete_applet(VCardApplet *applet)
-{
- if (applet == NULL) {
- return;
- }
- if (applet->applet_private_free) {
- applet->applet_private_free(applet->applet_private);
- }
- g_free(applet->aid);
- g_free(applet);
-}
-
-/* accessor */
-void
-vcard_set_applet_private(VCardApplet *applet, VCardAppletPrivate *private,
- VCardAppletPrivateFree private_free)
-{
- if (applet->applet_private_free) {
- applet->applet_private_free(applet->applet_private);
- }
- applet->applet_private = private;
- applet->applet_private_free = private_free;
-}
-
-VCard *
-vcard_new(VCardEmul *private, VCardEmulFree private_free)
-{
- VCard *new_card;
-
- new_card = g_new0(VCard, 1);
- new_card->type = VCARD_VM;
- new_card->vcard_private = private;
- new_card->vcard_private_free = private_free;
- new_card->reference_count = 1;
- return new_card;
-}
-
-VCard *
-vcard_reference(VCard *vcard)
-{
- if (vcard == NULL) {
- return NULL;
- }
- vcard->reference_count++;
- return vcard;
-}
-
-void
-vcard_free(VCard *vcard)
-{
- VCardApplet *current_applet;
- VCardApplet *next_applet;
-
- if (vcard == NULL) {
- return;
- }
- vcard->reference_count--;
- if (vcard->reference_count != 0) {
- return;
- }
- if (vcard->vcard_private_free) {
- (*vcard->vcard_private_free)(vcard->vcard_private);
- }
- for (current_applet = vcard->applet_list; current_applet;
- current_applet = next_applet) {
- next_applet = current_applet->next;
- vcard_delete_applet(current_applet);
- }
- vcard_buffer_response_delete(vcard->vcard_buffer_response);
- g_free(vcard);
-}
-
-void
-vcard_get_atr(VCard *vcard, unsigned char *atr, int *atr_len)
-{
- if (vcard->vcard_get_atr) {
- (*vcard->vcard_get_atr)(vcard, atr, atr_len);
- return;
- }
- vcard_emul_get_atr(vcard, atr, atr_len);
-}
-
-void
-vcard_set_atr_func(VCard *card, VCardGetAtr vcard_get_atr)
-{
- card->vcard_get_atr = vcard_get_atr;
-}
-
-
-VCardStatus
-vcard_add_applet(VCard *card, VCardApplet *applet)
-{
- applet->next = card->applet_list;
- card->applet_list = applet;
- /* if our card-type is direct, always call the applet */
- if (card->type == VCARD_DIRECT) {
- int i;
-
- for (i = 0; i < MAX_CHANNEL; i++) {
- card->current_applet[i] = applet;
- }
- }
- return VCARD_DONE;
-}
-
-/*
- * manage applets
- */
-VCardApplet *
-vcard_find_applet(VCard *card, unsigned char *aid, int aid_len)
-{
- VCardApplet *current_applet;
-
- for (current_applet = card->applet_list; current_applet;
- current_applet = current_applet->next) {
- if (current_applet->aid_len != aid_len) {
- continue;
- }
- if (memcmp(current_applet->aid, aid, aid_len) == 0) {
- break;
- }
- }
- return current_applet;
-}
-
-unsigned char *
-vcard_applet_get_aid(VCardApplet *applet, int *aid_len)
-{
- if (applet == NULL) {
- return NULL;
- }
- *aid_len = applet->aid_len;
- return applet->aid;
-}
-
-
-void
-vcard_select_applet(VCard *card, int channel, VCardApplet *applet)
-{
- assert(channel < MAX_CHANNEL);
-
- /* If using an emulated card, make sure to log out of any already logged in
- * session. */
- vcard_emul_logout(card);
-
- card->current_applet[channel] = applet;
- /* reset the applet */
- if (applet && applet->reset_applet) {
- applet->reset_applet(card, channel);
- }
-}
-
-VCardAppletPrivate *
-vcard_get_current_applet_private(VCard *card, int channel)
-{
- VCardApplet *applet = card->current_applet[channel];
-
- if (applet == NULL) {
- return NULL;
- }
- return applet->applet_private;
-}
-
-VCardStatus
-vcard_process_applet_apdu(VCard *card, VCardAPDU *apdu,
- VCardResponse **response)
-{
- if (card->current_applet[apdu->a_channel]) {
- return card->current_applet[apdu->a_channel]->process_apdu(
- card, apdu, response);
- }
- return VCARD_NEXT;
-}
-
-/*
- * Accessor functions
- */
-/* accessor functions for the response buffer */
-VCardBufferResponse *
-vcard_get_buffer_response(VCard *card)
-{
- return card->vcard_buffer_response;
-}
-
-void
-vcard_set_buffer_response(VCard *card, VCardBufferResponse *buffer)
-{
- card->vcard_buffer_response = buffer;
-}
-
-
-/* accessor functions for the type */
-VCardType
-vcard_get_type(VCard *card)
-{
- return card->type;
-}
-
-void
-vcard_set_type(VCard *card, VCardType type)
-{
- card->type = type;
-}
-
-/* accessor for private data */
-VCardEmul *
-vcard_get_private(VCard *vcard)
-{
- return vcard->vcard_private;
-}
-
diff --git a/libcacard/vcard.h b/libcacard/vcard.h
deleted file mode 100644
index 47dc70382b..0000000000
--- a/libcacard/vcard.h
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
- * See the COPYING.LIB file in the top-level directory.
- */
-#ifndef VCARD_H
-#define VCARD_H 1
-
-#include "vcardt.h"
-
-/*
- * response buffer constructors and destructors.
- *
- * response buffers are used when we need to return more data than will fit in
- * a normal APDU response (nominally 254 bytes).
- */
-VCardBufferResponse *vcard_buffer_response_new(unsigned char *buffer, int size);
-void vcard_buffer_response_delete(VCardBufferResponse *buffer_response);
-
-
-/*
- * clean up state on reset
- */
-void vcard_reset(VCard *card, VCardPower power);
-
-/*
- * applet utilities
- */
-/*
- * Constructor for a VCardApplet
- */
-VCardApplet *vcard_new_applet(VCardProcessAPDU applet_process_function,
- VCardResetApplet applet_reset_function,
- unsigned char *aid, int aid_len);
-
-/*
- * destructor for a VCardApplet
- * Can be called with a NULL applet
- */
-void vcard_delete_applet(VCardApplet *applet);
-
-/* accessor - set the card type specific private data */
-void vcard_set_applet_private(VCardApplet *applet, VCardAppletPrivate *_private,
- VCardAppletPrivateFree private_free);
-
-/* set type of vcard */
-void vcard_set_type(VCard *card, VCardType type);
-
-/*
- * utilities interacting with the current applet
- */
-/* add a new applet to a card */
-VCardStatus vcard_add_applet(VCard *card, VCardApplet *applet);
-/* find the applet on the card with the given aid */
-VCardApplet *vcard_find_applet(VCard *card, unsigned char *aid, int aid_len);
-/* set the following applet to be current on the given channel */
-void vcard_select_applet(VCard *card, int channel, VCardApplet *applet);
-/* get the card type specific private data on the given channel */
-VCardAppletPrivate *vcard_get_current_applet_private(VCard *card, int channel);
-/* fetch the applet's id */
-unsigned char *vcard_applet_get_aid(VCardApplet *applet, int *aid_len);
-
-/* process the apdu for the current selected applet/file */
-VCardStatus vcard_process_applet_apdu(VCard *card, VCardAPDU *apdu,
- VCardResponse **response);
-/*
- * VCard utilities
- */
-/* constructor */
-VCard *vcard_new(VCardEmul *_private, VCardEmulFree private_free);
-/* get a reference */
-VCard *vcard_reference(VCard *);
-/* destructor (reference counted) */
-void vcard_free(VCard *);
-/* get the atr from the card */
-void vcard_get_atr(VCard *card, unsigned char *atr, int *atr_len);
-void vcard_set_atr_func(VCard *card, VCardGetAtr vcard_get_atr);
-
-/* accessor functions for the response buffer */
-VCardBufferResponse *vcard_get_buffer_response(VCard *card);
-void vcard_set_buffer_response(VCard *card, VCardBufferResponse *buffer);
-/* accessor functions for the type */
-VCardType vcard_get_type(VCard *card);
-/* get the private data */
-VCardEmul *vcard_get_private(VCard *card);
-
-#endif
diff --git a/libcacard/vcard_emul.h b/libcacard/vcard_emul.h
deleted file mode 100644
index f09ee98dc8..0000000000
--- a/libcacard/vcard_emul.h
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * This is the actual card emulator.
- *
- * These functions can be implemented in different ways on different platforms
- * using the underlying system primitives. For Linux it uses NSS, though direct
- * to PKCS #11, openssl+pkcs11, or even gnu crypto libraries+pkcs #11 could be
- * used. On Windows CAPI could be used.
- *
- * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
- * See the COPYING.LIB file in the top-level directory.
- */
-
-#ifndef VCARD_EMUL_H
-#define VCARD_EMUL_H 1
-
-#include "card_7816t.h"
-#include "vcard.h"
-#include "vcard_emul_type.h"
-
-/*
- * types
- */
-typedef enum {
- VCARD_EMUL_OK = 0,
- VCARD_EMUL_FAIL,
- /* return values by vcard_emul_init */
- VCARD_EMUL_INIT_ALREADY_INITED,
-} VCardEmulError;
-
-/* options are emul specific. call card_emul_parse_args to change a string
- * To an options struct */
-typedef struct VCardEmulOptionsStruct VCardEmulOptions;
-
-/*
- * Login functions
- */
-/* return the number of login attempts still possible on the card. if unknown,
- * return -1 */
-int vcard_emul_get_login_count(VCard *card);
-/* login into the card, return the 7816 status word (sw2 || sw1) */
-vcard_7816_status_t vcard_emul_login(VCard *card, unsigned char *pin,
- int pin_len);
-void vcard_emul_logout(VCard *card);
-
-/*
- * key functions
- */
-/* delete a key */
-void vcard_emul_delete_key(VCardKey *key);
-/* RSA sign/decrypt with the key, signature happens 'in place' */
-vcard_7816_status_t vcard_emul_rsa_op(VCard *card, VCardKey *key,
- unsigned char *buffer, int buffer_size);
-
-void vcard_emul_reset(VCard *card, VCardPower power);
-void vcard_emul_get_atr(VCard *card, unsigned char *atr, int *atr_len);
-
-/* Re-insert of a card that has been removed by force removal */
-VCardEmulError vcard_emul_force_card_insert(VReader *vreader);
-/* Force a card removal even if the card is not physically removed */
-VCardEmulError vcard_emul_force_card_remove(VReader *vreader);
-
-VCardEmulOptions *vcard_emul_options(const char *args);
-VCardEmulError vcard_emul_init(const VCardEmulOptions *options);
-void vcard_emul_replay_insertion_events(void);
-void vcard_emul_usage(void);
-#endif
diff --git a/libcacard/vcard_emul_nss.c b/libcacard/vcard_emul_nss.c
deleted file mode 100644
index d9761eedc2..0000000000
--- a/libcacard/vcard_emul_nss.c
+++ /dev/null
@@ -1,1274 +0,0 @@
-/*
- * This is the actual card emulator.
- *
- * These functions can be implemented in different ways on different platforms
- * using the underlying system primitives. For Linux it uses NSS, though direct
- * to PKCS #11, openssl+pkcs11, or even gnu crypto libraries+pkcs #11 could be
- * used. On Windows CAPI could be used.
- *
- * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
- * See the COPYING.LIB file in the top-level directory.
- */
-
-/*
- * NSS headers
- */
-
-/* avoid including prototypes.h that redefines uint32 */
-#define NO_NSPR_10_SUPPORT
-
-#include <nss.h>
-#include <pk11pub.h>
-#include <cert.h>
-#include <key.h>
-#include <secmod.h>
-#include <prthread.h>
-#include <secerr.h>
-
-#include "glib-compat.h"
-
-#include "vcard.h"
-#include "card_7816t.h"
-#include "vcard_emul.h"
-#include "vreader.h"
-#include "vevent.h"
-
-#include "vcardt_internal.h"
-
-
-typedef enum {
- VCardEmulUnknown = -1,
- VCardEmulFalse = 0,
- VCardEmulTrue = 1
-} VCardEmulTriState;
-
-struct VCardKeyStruct {
- CERTCertificate *cert;
- PK11SlotInfo *slot;
- SECKEYPrivateKey *key;
- VCardEmulTriState failedX509;
-};
-
-
-typedef struct VirtualReaderOptionsStruct VirtualReaderOptions;
-
-struct VReaderEmulStruct {
- PK11SlotInfo *slot;
- VCardEmulType default_type;
- char *type_params;
- PRBool present;
- int series;
- VCard *saved_vcard;
-};
-
-/*
- * NSS Specific options
- */
-struct VirtualReaderOptionsStruct {
- char *name;
- char *vname;
- VCardEmulType card_type;
- char *type_params;
- char **cert_name;
- int cert_count;
-};
-
-struct VCardEmulOptionsStruct {
- void *nss_db;
- VirtualReaderOptions *vreader;
- int vreader_count;
- VCardEmulType hw_card_type;
- const char *hw_type_params;
- PRBool use_hw;
-};
-
-static int nss_emul_init;
-
-/* if we have more that just the slot, define
- * VCardEmulStruct here */
-
-/*
- * allocate the set of arrays for certs, cert_len, key
- */
-static void
-vcard_emul_alloc_arrays(unsigned char ***certsp, int **cert_lenp,
- VCardKey ***keysp, int cert_count)
-{
- *certsp = g_new(unsigned char *, cert_count);
- *cert_lenp = g_new(int, cert_count);
- *keysp = g_new(VCardKey *, cert_count);
-}
-
-/*
- * Emulator specific card information
- */
-typedef struct CardEmulCardStruct CardEmulPrivate;
-
-static VCardEmul *
-vcard_emul_new_card(PK11SlotInfo *slot)
-{
- PK11_ReferenceSlot(slot);
- /* currently we don't need anything other than the slot */
- return (VCardEmul *)slot;
-}
-
-static void
-vcard_emul_delete_card(VCardEmul *vcard_emul)
-{
- PK11SlotInfo *slot = (PK11SlotInfo *)vcard_emul;
- if (slot == NULL) {
- return;
- }
- PK11_FreeSlot(slot);
-}
-
-static PK11SlotInfo *
-vcard_emul_card_get_slot(VCard *card)
-{
- /* note, the card is holding the reference, no need to get another one */
- return (PK11SlotInfo *)vcard_get_private(card);
-}
-
-
-/*
- * key functions
- */
-/* private constructure */
-static VCardKey *
-vcard_emul_make_key(PK11SlotInfo *slot, CERTCertificate *cert)
-{
- VCardKey *key;
-
- key = g_new(VCardKey, 1);
- key->slot = PK11_ReferenceSlot(slot);
- key->cert = CERT_DupCertificate(cert);
- /* NOTE: if we aren't logged into the token, this could return NULL */
- /* NOTE: the cert is a temp cert, not necessarily the cert in the token,
- * use the DER version of this function */
- key->key = PK11_FindKeyByDERCert(slot, cert, NULL);
- key->failedX509 = VCardEmulUnknown;
- return key;
-}
-
-/* destructor */
-void
-vcard_emul_delete_key(VCardKey *key)
-{
- if (!nss_emul_init || (key == NULL)) {
- return;
- }
- if (key->key) {
- SECKEY_DestroyPrivateKey(key->key);
- key->key = NULL;
- }
- if (key->cert) {
- CERT_DestroyCertificate(key->cert);
- }
- if (key->slot) {
- PK11_FreeSlot(key->slot);
- }
-}
-
-/*
- * grab the nss key from a VCardKey. If it doesn't exist, try to look it up
- */
-static SECKEYPrivateKey *
-vcard_emul_get_nss_key(VCardKey *key)
-{
- if (key->key) {
- return key->key;
- }
- /* NOTE: if we aren't logged into the token, this could return NULL */
- key->key = PK11_FindPrivateKeyFromCert(key->slot, key->cert, NULL);
- return key->key;
-}
-
-/*
- * Map NSS errors to 7816 errors
- */
-static vcard_7816_status_t
-vcard_emul_map_error(int error)
-{
- switch (error) {
- case SEC_ERROR_TOKEN_NOT_LOGGED_IN:
- return VCARD7816_STATUS_ERROR_CONDITION_NOT_SATISFIED;
- case SEC_ERROR_BAD_DATA:
- case SEC_ERROR_OUTPUT_LEN:
- case SEC_ERROR_INPUT_LEN:
- case SEC_ERROR_INVALID_ARGS:
- case SEC_ERROR_INVALID_ALGORITHM:
- case SEC_ERROR_NO_KEY:
- case SEC_ERROR_INVALID_KEY:
- case SEC_ERROR_DECRYPTION_DISALLOWED:
- return VCARD7816_STATUS_ERROR_DATA_INVALID;
- case SEC_ERROR_NO_MEMORY:
- return VCARD7816_STATUS_EXC_ERROR_MEMORY_FAILURE;
- }
- return VCARD7816_STATUS_EXC_ERROR_CHANGE;
-}
-
-/* RSA sign/decrypt with the key, signature happens 'in place' */
-vcard_7816_status_t
-vcard_emul_rsa_op(VCard *card, VCardKey *key,
- unsigned char *buffer, int buffer_size)
-{
- SECKEYPrivateKey *priv_key;
- unsigned signature_len;
- PK11SlotInfo *slot;
- SECStatus rv;
- unsigned char buf[2048];
- unsigned char *bp = NULL;
- int pad_len;
- vcard_7816_status_t ret = VCARD7816_STATUS_SUCCESS;
-
- if ((!nss_emul_init) || (key == NULL)) {
- /* couldn't get the key, indicate that we aren't logged in */
- return VCARD7816_STATUS_ERROR_CONDITION_NOT_SATISFIED;
- }
- priv_key = vcard_emul_get_nss_key(key);
- if (priv_key == NULL) {
- /* couldn't get the key, indicate that we aren't logged in */
- return VCARD7816_STATUS_ERROR_CONDITION_NOT_SATISFIED;
- }
- slot = vcard_emul_card_get_slot(card);
-
- /*
- * this is only true of the rsa signature
- */
- signature_len = PK11_SignatureLen(priv_key);
- if (buffer_size != signature_len) {
- return VCARD7816_STATUS_ERROR_DATA_INVALID;
- }
- /* be able to handle larger keys if necessariy */
- bp = &buf[0];
- if (sizeof(buf) < signature_len) {
- bp = g_malloc(signature_len);
- }
-
- /*
- * do the raw operations. Some tokens claim to do CKM_RSA_X_509, but then
- * choke when they try to do the actual operations. Try to detect
- * those cases and treat them as if the token didn't claim support for
- * X_509.
- */
- if (key->failedX509 != VCardEmulTrue
- && PK11_DoesMechanism(slot, CKM_RSA_X_509)) {
- rv = PK11_PrivDecryptRaw(priv_key, bp, &signature_len, signature_len,
- buffer, buffer_size);
- if (rv == SECSuccess) {
- assert(buffer_size == signature_len);
- memcpy(buffer, bp, signature_len);
- key->failedX509 = VCardEmulFalse;
- goto cleanup;
- }
- /*
- * we've had a successful X509 operation, this failure must be
- * somethine else
- */
- if (key->failedX509 == VCardEmulFalse) {
- ret = vcard_emul_map_error(PORT_GetError());
- goto cleanup;
- }
- /*
- * key->failedX509 must be Unknown at this point, try the
- * non-x_509 case
- */
- }
- /* token does not support CKM_RSA_X509, emulate that with CKM_RSA_PKCS */
- /* is this a PKCS #1 formatted signature? */
- if ((buffer[0] == 0) && (buffer[1] == 1)) {
- int i;
-
- for (i = 2; i < buffer_size; i++) {
- /* rsa signature pad */
- if (buffer[i] != 0xff) {
- break;
- }
- }
- if ((i < buffer_size) && (buffer[i] == 0)) {
- /* yes, we have a properly formatted PKCS #1 signature */
- /*
- * NOTE: even if we accidentally got an encrypt buffer, which
- * through sheer luck started with 00, 01, ff, 00, it won't matter
- * because the resulting Sign operation will effectively decrypt
- * the real buffer.
- */
- SECItem signature;
- SECItem hash;
-
- i++;
- hash.data = &buffer[i];
- hash.len = buffer_size - i;
- signature.data = bp;
- signature.len = signature_len;
- rv = PK11_Sign(priv_key, &signature, &hash);
- if (rv != SECSuccess) {
- ret = vcard_emul_map_error(PORT_GetError());
- goto cleanup;
- }
- assert(buffer_size == signature.len);
- memcpy(buffer, bp, signature.len);
- /*
- * we got here because either the X509 attempt failed, or the
- * token couldn't do the X509 operation, in either case stay
- * with the PKCS version for future operations on this key
- */
- key->failedX509 = VCardEmulTrue;
- goto cleanup;
- }
- }
- pad_len = buffer_size - signature_len;
- assert(pad_len < 4);
- /*
- * OK now we've decrypted the payload, package it up in PKCS #1 for the
- * upper layer.
- */
- buffer[0] = 0;
- buffer[1] = 2; /* RSA_encrypt */
- pad_len -= 3; /* format is 0 || 2 || pad || 0 || data */
- /*
- * padding for PKCS #1 encrypted data is a string of random bytes. The
- * random butes protect against potential decryption attacks against RSA.
- * Since PrivDecrypt has already stripped those bytes, we can't reconstruct
- * them. This shouldn't matter to the upper level code which should just
- * strip this code out anyway, so We'll pad with a constant 3.
- */
- memset(&buffer[2], 0x03, pad_len);
- pad_len += 2; /* index to the end of the pad */
- buffer[pad_len] = 0;
- pad_len++; /* index to the start of the data */
- memcpy(&buffer[pad_len], bp, signature_len);
- /*
- * we got here because either the X509 attempt failed, or the
- * token couldn't do the X509 operation, in either case stay
- * with the PKCS version for future operations on this key
- */
- key->failedX509 = VCardEmulTrue;
-cleanup:
- if (bp != buf) {
- g_free(bp);
- }
- return ret;
-}
-
-/*
- * Login functions
- */
-/* return the number of login attempts still possible on the card. if unknown,
- * return -1 */
-int
-vcard_emul_get_login_count(VCard *card)
-{
- return -1;
-}
-
-/* login into the card, return the 7816 status word (sw2 || sw1) */
-vcard_7816_status_t
-vcard_emul_login(VCard *card, unsigned char *pin, int pin_len)
-{
- PK11SlotInfo *slot;
- unsigned char *pin_string;
- int i;
- SECStatus rv;
-
- if (!nss_emul_init) {
- return VCARD7816_STATUS_ERROR_CONDITION_NOT_SATISFIED;
- }
- slot = vcard_emul_card_get_slot(card);
- /* We depend on the PKCS #11 module internal login state here because we
- * create a separate process to handle each guest instance. If we needed
- * to handle multiple guests from one process, then we would need to keep
- * a lot of extra state in our card structure
- * */
- pin_string = g_malloc(pin_len+1);
- memcpy(pin_string, pin, pin_len);
- pin_string[pin_len] = 0;
-
- /* handle CAC expanded pins correctly */
- for (i = pin_len-1; i >= 0 && (pin_string[i] == 0xff); i--) {
- pin_string[i] = 0;
- }
-
- rv = PK11_Authenticate(slot, PR_FALSE, pin_string);
- memset(pin_string, 0, pin_len); /* don't let the pin hang around in memory
- to be snooped */
- g_free(pin_string);
- if (rv == SECSuccess) {
- return VCARD7816_STATUS_SUCCESS;
- }
- /* map the error from port get error */
- return VCARD7816_STATUS_ERROR_CONDITION_NOT_SATISFIED;
-}
-
-void
-vcard_emul_logout(VCard *card)
-{
- PK11SlotInfo *slot;
-
- if (!nss_emul_init) {
- return;
- }
-
- slot = vcard_emul_card_get_slot(card);
- if (PK11_IsLoggedIn(slot, NULL)) {
- PK11_Logout(slot); /* NOTE: ignoring SECStatus return value */
- }
-}
-
-void
-vcard_emul_reset(VCard *card, VCardPower power)
-{
- /*
- * if we reset the card (either power on or power off), we lose our login
- * state
- */
- vcard_emul_logout(card);
-
- /* TODO: we may also need to send insertion/removal events? */
-}
-
-static VReader *
-vcard_emul_find_vreader_from_slot(PK11SlotInfo *slot)
-{
- VReaderList *reader_list = vreader_get_reader_list();
- VReaderListEntry *current_entry;
-
- if (reader_list == NULL) {
- return NULL;
- }
- for (current_entry = vreader_list_get_first(reader_list); current_entry;
- current_entry = vreader_list_get_next(current_entry)) {
- VReader *reader = vreader_list_get_reader(current_entry);
- VReaderEmul *reader_emul = vreader_get_private(reader);
- if (reader_emul->slot == slot) {
- vreader_list_delete(reader_list);
- return reader;
- }
- vreader_free(reader);
- }
-
- vreader_list_delete(reader_list);
- return NULL;
-}
-
-/*
- * create a new reader emul
- */
-static VReaderEmul *
-vreader_emul_new(PK11SlotInfo *slot, VCardEmulType type, const char *params)
-{
- VReaderEmul *new_reader_emul;
-
- new_reader_emul = g_new(VReaderEmul, 1);
-
- new_reader_emul->slot = PK11_ReferenceSlot(slot);
- new_reader_emul->default_type = type;
- new_reader_emul->type_params = g_strdup(params);
- new_reader_emul->present = PR_FALSE;
- new_reader_emul->series = 0;
- new_reader_emul->saved_vcard = NULL;
- return new_reader_emul;
-}
-
-static void
-vreader_emul_delete(VReaderEmul *vreader_emul)
-{
- if (vreader_emul == NULL) {
- return;
- }
- if (vreader_emul->slot) {
- PK11_FreeSlot(vreader_emul->slot);
- }
- g_free(vreader_emul->type_params);
- g_free(vreader_emul);
-}
-
-/*
- * TODO: move this to emulater non-specific file
- */
-static VCardEmulType
-vcard_emul_get_type(VReader *vreader)
-{
- VReaderEmul *vreader_emul;
-
- vreader_emul = vreader_get_private(vreader);
- if (vreader_emul && vreader_emul->default_type != VCARD_EMUL_NONE) {
- return vreader_emul->default_type;
- }
-
- return vcard_emul_type_select(vreader);
-}
-/*
- * TODO: move this to emulater non-specific file
- */
-static const char *
-vcard_emul_get_type_params(VReader *vreader)
-{
- VReaderEmul *vreader_emul;
-
- vreader_emul = vreader_get_private(vreader);
- if (vreader_emul && vreader_emul->type_params) {
- return vreader_emul->type_params;
- }
-
- return "";
-}
-
-/* pull the slot out of the reader private data */
-static PK11SlotInfo *
-vcard_emul_reader_get_slot(VReader *vreader)
-{
- VReaderEmul *vreader_emul = vreader_get_private(vreader);
- if (vreader_emul == NULL) {
- return NULL;
- }
- return vreader_emul->slot;
-}
-
-/*
- * Card ATR's map to physical cards. vcard_alloc_atr will set appropriate
- * historical bytes for any software emulated card. The remaining bytes can be
- * used to indicate the actual emulator
- */
-static unsigned char *nss_atr;
-static int nss_atr_len;
-
-void
-vcard_emul_get_atr(VCard *card, unsigned char *atr, int *atr_len)
-{
- int len;
- assert(atr != NULL);
-
- if (nss_atr == NULL) {
- nss_atr = vcard_alloc_atr("NSS", &nss_atr_len);
- }
- len = MIN(nss_atr_len, *atr_len);
- memcpy(atr, nss_atr, len);
- *atr_len = len;
-}
-
-/*
- * create a new card from certs and keys
- */
-static VCard *
-vcard_emul_make_card(VReader *reader,
- unsigned char * const *certs, int *cert_len,
- VCardKey *keys[], int cert_count)
-{
- VCardEmul *vcard_emul;
- VCard *vcard;
- PK11SlotInfo *slot;
- VCardEmulType type;
- const char *params;
-
- type = vcard_emul_get_type(reader);
-
- /* ignore the inserted card */
- if (type == VCARD_EMUL_NONE) {
- return NULL;
- }
- slot = vcard_emul_reader_get_slot(reader);
- if (slot == NULL) {
- return NULL;
- }
-
- params = vcard_emul_get_type_params(reader);
- /* params these can be NULL */
-
- vcard_emul = vcard_emul_new_card(slot);
- if (vcard_emul == NULL) {
- return NULL;
- }
- vcard = vcard_new(vcard_emul, vcard_emul_delete_card);
- if (vcard == NULL) {
- vcard_emul_delete_card(vcard_emul);
- return NULL;
- }
- vcard_init(reader, vcard, type, params, certs, cert_len, keys, cert_count);
- return vcard;
-}
-
-
-/*
- * 'clone' a physical card as a virtual card
- */
-static VCard *
-vcard_emul_mirror_card(VReader *vreader)
-{
- /*
- * lookup certs using the C_FindObjects. The Stan Cert handle won't give
- * us the real certs until we log in.
- */
- PK11GenericObject *firstObj, *thisObj;
- int cert_count;
- unsigned char **certs;
- int *cert_len;
- VCardKey **keys;
- PK11SlotInfo *slot;
- VCard *card;
-
- slot = vcard_emul_reader_get_slot(vreader);
- if (slot == NULL) {
- return NULL;
- }
-
- firstObj = PK11_FindGenericObjects(slot, CKO_CERTIFICATE);
- if (firstObj == NULL) {
- return NULL;
- }
-
- /* count the certs */
- cert_count = 0;
- for (thisObj = firstObj; thisObj;
- thisObj = PK11_GetNextGenericObject(thisObj)) {
- cert_count++;
- }
-
- /* allocate the arrays */
- vcard_emul_alloc_arrays(&certs, &cert_len, &keys, cert_count);
-
- /* fill in the arrays */
- cert_count = 0;
- for (thisObj = firstObj; thisObj;
- thisObj = PK11_GetNextGenericObject(thisObj)) {
- SECItem derCert;
- CERTCertificate *cert;
- SECStatus rv;
-
- rv = PK11_ReadRawAttribute(PK11_TypeGeneric, thisObj,
- CKA_VALUE, &derCert);
- if (rv != SECSuccess) {
- continue;
- }
- /* create floating temp cert. This gives us a cert structure even if
- * the token isn't logged in */
- cert = CERT_NewTempCertificate(CERT_GetDefaultCertDB(), &derCert,
- NULL, PR_FALSE, PR_TRUE);
- SECITEM_FreeItem(&derCert, PR_FALSE);
- if (cert == NULL) {
- continue;
- }
-
- certs[cert_count] = cert->derCert.data;
- cert_len[cert_count] = cert->derCert.len;
- keys[cert_count] = vcard_emul_make_key(slot, cert);
- cert_count++;
- CERT_DestroyCertificate(cert); /* key obj still has a reference */
- }
-
- /* now create the card */
- card = vcard_emul_make_card(vreader, certs, cert_len, keys, cert_count);
- g_free(certs);
- g_free(cert_len);
- g_free(keys);
-
- return card;
-}
-
-static VCardEmulType default_card_type = VCARD_EMUL_NONE;
-static const char *default_type_params = "";
-
-/*
- * This thread looks for card and reader insertions and puts events on the
- * event queue
- */
-static void
-vcard_emul_event_thread(void *arg)
-{
- PK11SlotInfo *slot;
- VReader *vreader;
- VReaderEmul *vreader_emul;
- VCard *vcard;
- SECMODModule *module = (SECMODModule *)arg;
-
- do {
- /*
- * XXX - the latency value doesn't matter one bit. you only get no
- * blocking (flags |= CKF_DONT_BLOCK) or PKCS11_WAIT_LATENCY (==500),
- * hard coded in coolkey. And it isn't coolkey's fault - the timeout
- * value we pass get's dropped on the floor before C_WaitForSlotEvent
- * is called.
- */
- slot = SECMOD_WaitForAnyTokenEvent(module, 0, 500);
- if (slot == NULL) {
- /* this could be just a no event indication */
- if (PORT_GetError() == SEC_ERROR_NO_EVENT) {
- continue;
- }
- break;
- }
- vreader = vcard_emul_find_vreader_from_slot(slot);
- if (vreader == NULL) {
- /* new vreader */
- vreader_emul = vreader_emul_new(slot, default_card_type,
- default_type_params);
- vreader = vreader_new(PK11_GetSlotName(slot), vreader_emul,
- vreader_emul_delete);
- PK11_FreeSlot(slot);
- slot = NULL;
- vreader_add_reader(vreader);
- vreader_free(vreader);
- continue;
- }
- /* card remove/insert */
- vreader_emul = vreader_get_private(vreader);
- if (PK11_IsPresent(slot)) {
- int series = PK11_GetSlotSeries(slot);
- if (series != vreader_emul->series) {
- if (vreader_emul->present) {
- vreader_insert_card(vreader, NULL);
- }
- vcard = vcard_emul_mirror_card(vreader);
- vreader_insert_card(vreader, vcard);
- vcard_free(vcard);
- }
- vreader_emul->series = series;
- vreader_emul->present = 1;
- vreader_free(vreader);
- PK11_FreeSlot(slot);
- continue;
- }
- if (vreader_emul->present) {
- vreader_insert_card(vreader, NULL);
- }
- vreader_emul->series = 0;
- vreader_emul->present = 0;
- PK11_FreeSlot(slot);
- vreader_free(vreader);
- } while (1);
-}
-
-/* if the card is inserted when we start up, make sure our state is correct */
-static void
-vcard_emul_init_series(VReader *vreader, VCard *vcard)
-{
- VReaderEmul *vreader_emul = vreader_get_private(vreader);
- PK11SlotInfo *slot = vreader_emul->slot;
-
- vreader_emul->present = PK11_IsPresent(slot);
- vreader_emul->series = PK11_GetSlotSeries(slot);
- if (vreader_emul->present == 0) {
- vreader_insert_card(vreader, NULL);
- }
-}
-
-/*
- * each module has a separate wait call, create a thread for each module that
- * we are using.
- */
-static void
-vcard_emul_new_event_thread(SECMODModule *module)
-{
- PR_CreateThread(PR_SYSTEM_THREAD, vcard_emul_event_thread,
- module, PR_PRIORITY_HIGH, PR_GLOBAL_THREAD,
- PR_UNJOINABLE_THREAD, 0);
-}
-
-static const VCardEmulOptions default_options = {
- .nss_db = NULL,
- .vreader = NULL,
- .vreader_count = 0,
- .hw_card_type = VCARD_EMUL_CAC,
- .hw_type_params = "",
- .use_hw = PR_TRUE
-};
-
-
-/*
- * NSS needs the app to supply a password prompt. In our case the only time
- * the password is supplied is as part of the Login APDU. The actual password
- * is passed in the pw_arg in that case. In all other cases pw_arg should be
- * NULL.
- */
-static char *
-vcard_emul_get_password(PK11SlotInfo *slot, PRBool retries, void *pw_arg)
-{
- /* if it didn't work the first time, don't keep trying */
- if (retries) {
- return NULL;
- }
- /* we are looking up a password when we don't have one in hand */
- if (pw_arg == NULL) {
- return NULL;
- }
- /* TODO: we really should verify that were are using the right slot */
- return PORT_Strdup(pw_arg);
-}
-
-/* Force a card removal even if the card is not physically removed */
-VCardEmulError
-vcard_emul_force_card_remove(VReader *vreader)
-{
- if (!nss_emul_init || (vreader_card_is_present(vreader) != VREADER_OK)) {
- return VCARD_EMUL_FAIL; /* card is already removed */
- }
-
- /* OK, remove it */
- vreader_insert_card(vreader, NULL);
- return VCARD_EMUL_OK;
-}
-
-/* Re-insert of a card that has been removed by force removal */
-VCardEmulError
-vcard_emul_force_card_insert(VReader *vreader)
-{
- VReaderEmul *vreader_emul;
- VCard *vcard;
-
- if (!nss_emul_init || (vreader_card_is_present(vreader) == VREADER_OK)) {
- return VCARD_EMUL_FAIL; /* card is already removed */
- }
- vreader_emul = vreader_get_private(vreader);
-
- /* if it's a softcard, get the saved vcard from the reader emul structure */
- if (vreader_emul->saved_vcard) {
- vcard = vcard_reference(vreader_emul->saved_vcard);
- } else {
- /* it must be a physical card, rebuild it */
- if (!PK11_IsPresent(vreader_emul->slot)) {
- /* physical card has been removed, not way to reinsert it */
- return VCARD_EMUL_FAIL;
- }
- vcard = vcard_emul_mirror_card(vreader);
- }
- vreader_insert_card(vreader, vcard);
- vcard_free(vcard);
-
- return VCARD_EMUL_OK;
-}
-
-
-static PRBool
-module_has_removable_hw_slots(SECMODModule *mod)
-{
- int i;
- PRBool ret = PR_FALSE;
- SECMODListLock *moduleLock = SECMOD_GetDefaultModuleListLock();
-
- if (!moduleLock) {
- PORT_SetError(SEC_ERROR_NOT_INITIALIZED);
- return ret;
- }
- SECMOD_GetReadLock(moduleLock);
- for (i = 0; i < mod->slotCount; i++) {
- PK11SlotInfo *slot = mod->slots[i];
- if (PK11_IsRemovable(slot) && PK11_IsHW(slot)) {
- ret = PR_TRUE;
- break;
- }
- }
- SECMOD_ReleaseReadLock(moduleLock);
- return ret;
-}
-
-/* Previously we returned FAIL if no readers found. This makes
- * no sense when using hardware, since there may be no readers connected
- * at the time vcard_emul_init is called, but they will be properly
- * recognized later. So Instead return FAIL only if no_hw==1 and no
- * vcards can be created (indicates error with certificates provided
- * or db), or if any other higher level error (NSS error, missing coolkey). */
-static int vcard_emul_init_called;
-
-VCardEmulError
-vcard_emul_init(const VCardEmulOptions *options)
-{
- SECStatus rv;
- PRBool has_readers = PR_FALSE;
- VReader *vreader;
- VReaderEmul *vreader_emul;
- SECMODListLock *module_lock;
- SECMODModuleList *module_list;
- SECMODModuleList *mlp;
- int i;
-
- if (vcard_emul_init_called) {
- return VCARD_EMUL_INIT_ALREADY_INITED;
- }
- vcard_emul_init_called = 1;
- vreader_init();
- vevent_queue_init();
-
- if (options == NULL) {
- options = &default_options;
- }
-
- /* first initialize NSS */
- if (options->nss_db) {
- rv = NSS_Init(options->nss_db);
- } else {
- gchar *path;
-#ifndef _WIN32
- path = g_strdup("/etc/pki/nssdb");
-#else
- if (g_get_system_config_dirs() == NULL ||
- g_get_system_config_dirs()[0] == NULL) {
- return VCARD_EMUL_FAIL;
- }
-
- path = g_build_filename(
- g_get_system_config_dirs()[0], "pki", "nssdb", NULL);
-#endif
-
- rv = NSS_Init(path);
- g_free(path);
- }
- if (rv != SECSuccess) {
- return VCARD_EMUL_FAIL;
- }
- /* Set password callback function */
- PK11_SetPasswordFunc(vcard_emul_get_password);
-
- /* set up soft cards emulated by software certs rather than physical cards
- * */
- for (i = 0; i < options->vreader_count; i++) {
- int j;
- int cert_count;
- unsigned char **certs;
- int *cert_len;
- VCardKey **keys;
- PK11SlotInfo *slot;
-
- slot = PK11_FindSlotByName(options->vreader[i].name);
- if (slot == NULL) {
- continue;
- }
- vreader_emul = vreader_emul_new(slot, options->vreader[i].card_type,
- options->vreader[i].type_params);
- vreader = vreader_new(options->vreader[i].vname, vreader_emul,
- vreader_emul_delete);
- vreader_add_reader(vreader);
-
- vcard_emul_alloc_arrays(&certs, &cert_len, &keys,
- options->vreader[i].cert_count);
-
- cert_count = 0;
- for (j = 0; j < options->vreader[i].cert_count; j++) {
- /* we should have a better way of identifying certs than by
- * nickname here */
- CERTCertificate *cert = PK11_FindCertFromNickname(
- options->vreader[i].cert_name[j],
- NULL);
- if (cert == NULL) {
- continue;
- }
- certs[cert_count] = cert->derCert.data;
- cert_len[cert_count] = cert->derCert.len;
- keys[cert_count] = vcard_emul_make_key(slot, cert);
- /* this is safe because the key is still holding a cert reference */
- CERT_DestroyCertificate(cert);
- cert_count++;
- }
- if (cert_count) {
- VCard *vcard = vcard_emul_make_card(vreader, certs, cert_len,
- keys, cert_count);
- vreader_insert_card(vreader, vcard);
- vcard_emul_init_series(vreader, vcard);
- /* allow insertion and removal of soft cards */
- vreader_emul->saved_vcard = vcard_reference(vcard);
- vcard_free(vcard);
- vreader_free(vreader);
- has_readers = PR_TRUE;
- }
- g_free(certs);
- g_free(cert_len);
- g_free(keys);
- }
-
- /* if we aren't suppose to use hw, skip looking up hardware tokens */
- if (!options->use_hw) {
- nss_emul_init = has_readers;
- return has_readers ? VCARD_EMUL_OK : VCARD_EMUL_FAIL;
- }
-
- /* make sure we have some PKCS #11 module loaded */
- module_lock = SECMOD_GetDefaultModuleListLock();
- module_list = SECMOD_GetDefaultModuleList();
- SECMOD_GetReadLock(module_lock);
- for (mlp = module_list; mlp; mlp = mlp->next) {
- SECMODModule *module = mlp->module;
- if (module_has_removable_hw_slots(module)) {
- break;
- }
- }
- SECMOD_ReleaseReadLock(module_lock);
-
- /* now examine all the slots, finding which should be readers */
- /* We should control this with options. For now we mirror out any
- * removable hardware slot */
- default_card_type = options->hw_card_type;
- default_type_params = g_strdup(options->hw_type_params);
-
- SECMOD_GetReadLock(module_lock);
- for (mlp = module_list; mlp; mlp = mlp->next) {
- SECMODModule *module = mlp->module;
-
- /* Ignore the internal module */
- if (module == NULL || module == SECMOD_GetInternalModule()) {
- continue;
- }
-
- for (i = 0; i < module->slotCount; i++) {
- PK11SlotInfo *slot = module->slots[i];
-
- /* only map removable HW slots */
- if (slot == NULL || !PK11_IsRemovable(slot) || !PK11_IsHW(slot)) {
- continue;
- }
- if (strcmp("E-Gate 0 0", PK11_GetSlotName(slot)) == 0) {
- /*
- * coolkey <= 1.1.0-20 emulates this reader if it can't find
- * any hardware readers. This causes problems, warn user of
- * problems.
- */
- fprintf(stderr, "known bad coolkey version - see "
- "https://bugzilla.redhat.com/show_bug.cgi?id=802435\n");
- continue;
- }
- vreader_emul = vreader_emul_new(slot, options->hw_card_type,
- options->hw_type_params);
- vreader = vreader_new(PK11_GetSlotName(slot), vreader_emul,
- vreader_emul_delete);
- vreader_add_reader(vreader);
-
- if (PK11_IsPresent(slot)) {
- VCard *vcard;
- vcard = vcard_emul_mirror_card(vreader);
- vreader_insert_card(vreader, vcard);
- vcard_emul_init_series(vreader, vcard);
- vcard_free(vcard);
- }
- }
- vcard_emul_new_event_thread(module);
- }
- SECMOD_ReleaseReadLock(module_lock);
- nss_emul_init = PR_TRUE;
-
- return VCARD_EMUL_OK;
-}
-
-/* Recreate card insert events for all readers (user should
- * deduce implied reader insert. perhaps do a reader insert as well?)
- */
-void
-vcard_emul_replay_insertion_events(void)
-{
- VReaderListEntry *current_entry;
- VReaderListEntry *next_entry;
- VReaderList *list = vreader_get_reader_list();
-
- for (current_entry = vreader_list_get_first(list); current_entry;
- current_entry = next_entry) {
- VReader *vreader = vreader_list_get_reader(current_entry);
- next_entry = vreader_list_get_next(current_entry);
- vreader_queue_card_event(vreader);
- }
-
- vreader_list_delete(list);
-}
-
-/*
- * Silly little functions to help parsing our argument string
- */
-static int
-count_tokens(const char *str, char token, char token_end)
-{
- int count = 0;
-
- for (; *str; str++) {
- if (*str == token) {
- count++;
- }
- if (*str == token_end) {
- break;
- }
- }
- return count;
-}
-
-static const char *
-strip(const char *str)
-{
- for (; *str && isspace(*str); str++) {
- }
- return str;
-}
-
-static const char *
-find_blank(const char *str)
-{
- for (; *str && !isspace(*str); str++) {
- }
- return str;
-}
-
-
-/*
- * We really want to use some existing argument parsing library here. That
- * would give us a consistent look */
-static VCardEmulOptions options;
-#define READER_STEP 4
-
-/* Expects "args" to be at the beginning of a token (ie right after the ','
- * ending the previous token), and puts the next token start in "token",
- * and its length in "token_length". "token" will not be nul-terminated.
- * After calling the macro, "args" will be advanced to the beginning of
- * the next token.
- * This macro may call continue or break.
- */
-#define NEXT_TOKEN(token) \
- (token) = args; \
- args = strpbrk(args, ",)"); \
- if (*args == 0) { \
- break; \
- } \
- if (*args == ')') { \
- args++; \
- continue; \
- } \
- (token##_length) = args - (token); \
- args = strip(args+1);
-
-VCardEmulOptions *
-vcard_emul_options(const char *args)
-{
- int reader_count = 0;
- VCardEmulOptions *opts;
-
- /* Allow the future use of allocating the options structure on the fly */
- memcpy(&options, &default_options, sizeof(options));
- opts = &options;
-
- do {
- args = strip(args); /* strip off the leading spaces */
- if (*args == ',') {
- continue;
- }
- /* soft=(slot_name,virt_name,emul_type,emul_flags,cert_1, (no eol)
- * cert_2,cert_3...) */
- if (strncmp(args, "soft=", 5) == 0) {
- const char *name;
- size_t name_length;
- const char *vname;
- size_t vname_length;
- const char *type_params;
- size_t type_params_length;
- char type_str[100];
- VCardEmulType type;
- int count, i;
- VirtualReaderOptions *vreaderOpt;
-
- args = strip(args + 5);
- if (*args != '(') {
- continue;
- }
- args = strip(args+1);
-
- NEXT_TOKEN(name)
- NEXT_TOKEN(vname)
- NEXT_TOKEN(type_params)
- type_params_length = MIN(type_params_length, sizeof(type_str)-1);
- memcpy(type_str, type_params, type_params_length);
- type_str[type_params_length] = '\0';
- type = vcard_emul_type_from_string(type_str);
-
- NEXT_TOKEN(type_params)
-
- if (*args == 0) {
- break;
- }
-
- if (opts->vreader_count >= reader_count) {
- reader_count += READER_STEP;
- opts->vreader = g_renew(VirtualReaderOptions, opts->vreader,
- reader_count);
- }
- vreaderOpt = &opts->vreader[opts->vreader_count];
- vreaderOpt->name = g_strndup(name, name_length);
- vreaderOpt->vname = g_strndup(vname, vname_length);
- vreaderOpt->card_type = type;
- vreaderOpt->type_params =
- g_strndup(type_params, type_params_length);
- count = count_tokens(args, ',', ')') + 1;
- vreaderOpt->cert_count = count;
- vreaderOpt->cert_name = g_new(char *, count);
- for (i = 0; i < count; i++) {
- const char *cert = args;
- args = strpbrk(args, ",)");
- vreaderOpt->cert_name[i] = g_strndup(cert, args - cert);
- args = strip(args+1);
- }
- if (*args == ')') {
- args++;
- }
- opts->vreader_count++;
- /* use_hw= */
- } else if (strncmp(args, "use_hw=", 7) == 0) {
- args = strip(args+7);
- if (*args == '0' || *args == 'N' || *args == 'n' || *args == 'F') {
- opts->use_hw = PR_FALSE;
- } else {
- opts->use_hw = PR_TRUE;
- }
- args = find_blank(args);
- /* hw_type= */
- } else if (strncmp(args, "hw_type=", 8) == 0) {
- args = strip(args+8);
- opts->hw_card_type = vcard_emul_type_from_string(args);
- args = find_blank(args);
- /* hw_params= */
- } else if (strncmp(args, "hw_params=", 10) == 0) {
- const char *params;
- args = strip(args+10);
- params = args;
- args = find_blank(args);
- opts->hw_type_params = g_strndup(params, args-params);
- /* db="/data/base/path" */
- } else if (strncmp(args, "db=", 3) == 0) {
- const char *db;
- args = strip(args+3);
- if (*args != '"') {
- continue;
- }
- args++;
- db = args;
- args = strpbrk(args, "\"\n");
- opts->nss_db = g_strndup(db, args-db);
- if (*args != 0) {
- args++;
- }
- } else {
- args = find_blank(args);
- }
- } while (*args != 0);
-
- return opts;
-}
-
-void
-vcard_emul_usage(void)
-{
- fprintf(stderr,
-"emul args: comma separated list of the following arguments\n"
-" db={nss_database} (default sql:/etc/pki/nssdb)\n"
-" use_hw=[yes|no] (default yes)\n"
-" hw_type={card_type_to_emulate} (default CAC)\n"
-" hw_param={param_for_card} (default \"\")\n"
-" soft=({slot_name},{vreader_name},{card_type_to_emulate},{params_for_card},\n"
-" {cert1},{cert2},{cert3} (default none)\n"
-"\n"
-" {nss_database} The location of the NSS cert & key database\n"
-" {card_type_to_emulate} What card interface to present to the guest\n"
-" {param_for_card} Card interface specific parameters\n"
-" {slot_name} NSS slot that contains the certs\n"
-" {vreader_name} Virtual reader name to present to the guest\n"
-" {certN} Nickname of the certificate n on the virtual card\n"
-"\n"
-"These parameters come as a single string separated by blanks or newlines."
-"\n"
-"Unless use_hw is set to no, all tokens that look like removable hardware\n"
-"tokens will be presented to the guest using the emulator specified by\n"
-"hw_type, and parameters of hw_param.\n"
-"\n"
-"If more one or more soft= parameters are specified, these readers will be\n"
-"presented to the guest\n");
-}
diff --git a/libcacard/vcard_emul_type.c b/libcacard/vcard_emul_type.c
deleted file mode 100644
index 59a1458201..0000000000
--- a/libcacard/vcard_emul_type.c
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * This file contains utility functions which abstract the different card
- * types. The goal is that new card types can easily be added by simply
- * changing this file and vcard_emul_type.h. It is currently not a requirement
- * to dynamically add new card types.
- *
- * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
- * See the COPYING.LIB file in the top-level directory.
- */
-
-#include <strings.h>
-#include "vcardt.h"
-#include "vcard_emul_type.h"
-#include "cac.h"
-
-VCardStatus vcard_init(VReader *vreader, VCard *vcard,
- VCardEmulType type, const char *params,
- unsigned char *const *cert, int cert_len[],
- VCardKey *key[], int cert_count)
-{
- switch (type) {
- case VCARD_EMUL_NONE:
- break;
- case VCARD_EMUL_CAC:
- return cac_card_init(vreader, vcard, params,
- cert, cert_len, key, cert_count);
- /* add new ones here */
- default:
- break;
- }
- return VCARD_FAIL;
-}
-
-VCardEmulType vcard_emul_type_select(VReader *vreader)
-{
-#ifdef notdef
- /* since there is only one emulator no need to call this function */
- if (cac_is_cac_card(vreader) == VCARD_DONE) {
- return VCARD_EMUL_CAC;
- }
-#endif
- /* return the default */
- return VCARD_EMUL_CAC;
-}
-
-VCardEmulType vcard_emul_type_from_string(const char *type_string)
-{
- if (strcasecmp(type_string, "CAC") == 0) {
- return VCARD_EMUL_CAC;
- }
-#ifdef USE_PASSTHRU
- if (strcasecmp(type_string, "PASSTHRU") == 0) {
- return VCARD_EMUL_PASSTHRU;
- }
-#endif
- return VCARD_EMUL_NONE;
-}
diff --git a/libcacard/vcard_emul_type.h b/libcacard/vcard_emul_type.h
deleted file mode 100644
index 0242f40eb1..0000000000
--- a/libcacard/vcard_emul_type.h
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * This header file abstracts the different card types. The goal is new card
- * types can easily be added by simply changing this file and
- * vcard_emul_type.c. It is currently not a requirement to dynamically add new
- * card types.
- *
- * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
- * See the COPYING.LIB file in the top-level directory.
- */
-
-#ifndef VCARD_EMUL_TYPE_H
-#define VCARD_EMUL_TYPE_H 1
-#include "vcardt.h"
-#include "vreadert.h"
-
-/*
- * types
- */
-typedef enum {
- VCARD_EMUL_NONE = 0,
- VCARD_EMUL_CAC,
- VCARD_EMUL_PASSTHRU
-} VCardEmulType;
-
-/* functions used by the rest of the emulator */
-VCardStatus vcard_init(VReader *vreader, VCard *vcard, VCardEmulType type,
- const char *params, unsigned char * const *cert,
- int cert_len[], VCardKey *key[], int cert_count);
-VCardEmulType vcard_emul_type_select(VReader *vreader);
-VCardEmulType vcard_emul_type_from_string(const char *type_string);
-
-#endif
diff --git a/libcacard/vcardt.c b/libcacard/vcardt.c
deleted file mode 100644
index c67de2f3c1..0000000000
--- a/libcacard/vcardt.c
+++ /dev/null
@@ -1,40 +0,0 @@
-#include <stdlib.h>
-#include <string.h>
-#include <glib.h>
-
-#include "vcardt.h"
-
-#include "vcardt_internal.h"
-
-/* create an ATR with appropriate historical bytes */
-#define ATR_TS_DIRECT_CONVENTION 0x3b
-#define ATR_TA_PRESENT 0x10
-#define ATR_TB_PRESENT 0x20
-#define ATR_TC_PRESENT 0x40
-#define ATR_TD_PRESENT 0x80
-
-unsigned char *vcard_alloc_atr(const char *postfix, int *atr_len)
-{
- int postfix_len;
- const char prefix[] = "VCARD_";
- const char default_postfix[] = "DEFAULT";
- const int prefix_len = sizeof(prefix) - 1;
- int total_len;
- unsigned char *atr;
-
- if (postfix == NULL) {
- postfix = default_postfix;
- }
- postfix_len = strlen(postfix);
- total_len = 3 + prefix_len + postfix_len;
- atr = g_malloc(total_len);
- atr[0] = ATR_TS_DIRECT_CONVENTION;
- atr[1] = ATR_TD_PRESENT + prefix_len + postfix_len;
- atr[2] = 0x00;
- memcpy(&atr[3], prefix, prefix_len);
- memcpy(&atr[3 + prefix_len], postfix, postfix_len);
- if (atr_len) {
- *atr_len = total_len;
- }
- return atr;
-}
diff --git a/libcacard/vcardt.h b/libcacard/vcardt.h
deleted file mode 100644
index 795e265304..0000000000
--- a/libcacard/vcardt.h
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
- * See the COPYING.LIB file in the top-level directory.
- */
-#ifndef VCARDT_H
-#define VCARDT_H 1
-
-/*
- * these should come from some common spice header file
- */
-#include <assert.h>
-#ifndef MIN
-#define MIN(x, y) ((x) > (y) ? (y) : (x))
-#define MAX(x, y) ((x) > (y) ? (x) : (y))
-#endif
-
-typedef struct VCardStruct VCard;
-typedef struct VCardAPDUStruct VCardAPDU;
-typedef struct VCardResponseStruct VCardResponse;
-typedef struct VCardBufferResponseStruct VCardBufferResponse;
-typedef struct VCardAppletStruct VCardApplet;
-typedef struct VCardAppletPrivateStruct VCardAppletPrivate;
-typedef struct VCardKeyStruct VCardKey; /* opaque */
-typedef struct VCardEmulStruct VCardEmul;
-
-#define MAX_CHANNEL 4
-
-typedef enum {
- VCARD_DONE,
- VCARD_NEXT,
- VCARD_FAIL
-} VCardStatus;
-
-typedef enum {
- VCARD_FILE_SYSTEM,
- VCARD_VM,
- VCARD_DIRECT
-} VCardType;
-
-typedef enum {
- VCARD_POWER_ON,
- VCARD_POWER_OFF
-} VCardPower;
-
-typedef VCardStatus (*VCardProcessAPDU)(VCard *card, VCardAPDU *apdu,
- VCardResponse **response);
-typedef VCardStatus (*VCardResetApplet)(VCard *card, int channel);
-typedef void (*VCardAppletPrivateFree) (VCardAppletPrivate *);
-typedef void (*VCardEmulFree) (VCardEmul *);
-typedef void (*VCardGetAtr) (VCard *, unsigned char *atr, int *atr_len);
-
-struct VCardBufferResponseStruct {
- unsigned char *buffer;
- int buffer_len;
- unsigned char *current;
- int len;
-};
-
-#endif
diff --git a/libcacard/vcardt_internal.h b/libcacard/vcardt_internal.h
deleted file mode 100644
index e5c8d2dd3e..0000000000
--- a/libcacard/vcardt_internal.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef VCARDT_INTERNAL_H
-#define VCARDT_INTERNAL_H
-
-unsigned char *vcard_alloc_atr(const char *postfix, int *atr_len);
-
-#endif
diff --git a/libcacard/vevent.h b/libcacard/vevent.h
deleted file mode 100644
index 38c3482c35..0000000000
--- a/libcacard/vevent.h
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
- * See the COPYING.LIB file in the top-level directory.
- */
-#ifndef EVENT_H
-#define EVENT_H 1
-#include "eventt.h"
-#include "vreadert.h"
-#include "vcardt.h"
-
-VEvent *vevent_new(VEventType type, VReader *reader, VCard *card);
-void vevent_delete(VEvent *);
-
-/*
- * VEvent queueing services
- */
-void vevent_queue_vevent(VEvent *);
-void vevent_queue_init(void);
-
-/*
- * VEvent dequeing services
- */
-VEvent *vevent_wait_next_vevent(void);
-VEvent *vevent_get_next_vevent(void);
-
-
-#endif
diff --git a/libcacard/vreader.c b/libcacard/vreader.c
deleted file mode 100644
index 9725f46a74..0000000000
--- a/libcacard/vreader.c
+++ /dev/null
@@ -1,578 +0,0 @@
-/*
- * emulate the reader
- *
- * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
- * See the COPYING.LIB file in the top-level directory.
- */
-
-#ifdef G_LOG_DOMAIN
-#undef G_LOG_DOMAIN
-#endif
-#define G_LOG_DOMAIN "libcacard"
-
-#include "glib-compat.h"
-
-#include <string.h>
-
-#include "vcard.h"
-#include "vcard_emul.h"
-#include "card_7816.h"
-#include "vreader.h"
-#include "vevent.h"
-#include "cac.h" /* just for debugging defines */
-
-#define LIBCACARD_LOG_DOMAIN "libcacard"
-
-struct VReaderStruct {
- int reference_count;
- VCard *card;
- char *name;
- vreader_id_t id;
- CompatGMutex lock;
- VReaderEmul *reader_private;
- VReaderEmulFree reader_private_free;
-};
-
-/*
- * Debug helpers
- */
-
-static const char *
-apdu_ins_to_string(int ins)
-{
- switch (ins) {
- case VCARD7816_INS_MANAGE_CHANNEL:
- return "manage channel";
- case VCARD7816_INS_EXTERNAL_AUTHENTICATE:
- return "external authenticate";
- case VCARD7816_INS_GET_CHALLENGE:
- return "get challenge";
- case VCARD7816_INS_INTERNAL_AUTHENTICATE:
- return "internal authenticate";
- case VCARD7816_INS_ERASE_BINARY:
- return "erase binary";
- case VCARD7816_INS_READ_BINARY:
- return "read binary";
- case VCARD7816_INS_WRITE_BINARY:
- return "write binary";
- case VCARD7816_INS_UPDATE_BINARY:
- return "update binary";
- case VCARD7816_INS_READ_RECORD:
- return "read record";
- case VCARD7816_INS_WRITE_RECORD:
- return "write record";
- case VCARD7816_INS_UPDATE_RECORD:
- return "update record";
- case VCARD7816_INS_APPEND_RECORD:
- return "append record";
- case VCARD7816_INS_ENVELOPE:
- return "envelope";
- case VCARD7816_INS_PUT_DATA:
- return "put data";
- case VCARD7816_INS_GET_DATA:
- return "get data";
- case VCARD7816_INS_SELECT_FILE:
- return "select file";
- case VCARD7816_INS_VERIFY:
- return "verify";
- case VCARD7816_INS_GET_RESPONSE:
- return "get response";
- case CAC_GET_PROPERTIES:
- return "get properties";
- case CAC_GET_ACR:
- return "get acr";
- case CAC_READ_BUFFER:
- return "read buffer";
- case CAC_UPDATE_BUFFER:
- return "update buffer";
- case CAC_SIGN_DECRYPT:
- return "sign decrypt";
- case CAC_GET_CERTIFICATE:
- return "get certificate";
- }
- return "unknown";
-}
-
-/* manage locking */
-static inline void
-vreader_lock(VReader *reader)
-{
- g_mutex_lock(&reader->lock);
-}
-
-static inline void
-vreader_unlock(VReader *reader)
-{
- g_mutex_unlock(&reader->lock);
-}
-
-/*
- * vreader constructor
- */
-VReader *
-vreader_new(const char *name, VReaderEmul *private,
- VReaderEmulFree private_free)
-{
- VReader *reader;
-
- reader = g_new(VReader, 1);
- g_mutex_init(&reader->lock);
- reader->reference_count = 1;
- reader->name = g_strdup(name);
- reader->card = NULL;
- reader->id = (vreader_id_t)-1;
- reader->reader_private = private;
- reader->reader_private_free = private_free;
- return reader;
-}
-
-/* get a reference */
-VReader*
-vreader_reference(VReader *reader)
-{
- if (reader == NULL) {
- return NULL;
- }
- vreader_lock(reader);
- reader->reference_count++;
- vreader_unlock(reader);
- return reader;
-}
-
-/* free a reference */
-void
-vreader_free(VReader *reader)
-{
- if (reader == NULL) {
- return;
- }
- vreader_lock(reader);
- if (reader->reference_count-- > 1) {
- vreader_unlock(reader);
- return;
- }
- vreader_unlock(reader);
- g_mutex_clear(&reader->lock);
- if (reader->card) {
- vcard_free(reader->card);
- }
- g_free(reader->name);
- if (reader->reader_private_free) {
- reader->reader_private_free(reader->reader_private);
- }
- g_free(reader);
-}
-
-static VCard *
-vreader_get_card(VReader *reader)
-{
- VCard *card;
-
- vreader_lock(reader);
- card = vcard_reference(reader->card);
- vreader_unlock(reader);
- return card;
-}
-
-VReaderStatus
-vreader_card_is_present(VReader *reader)
-{
- VCard *card = vreader_get_card(reader);
-
- if (card == NULL) {
- return VREADER_NO_CARD;
- }
- vcard_free(card);
- return VREADER_OK;
-}
-
-vreader_id_t
-vreader_get_id(VReader *reader)
-{
- if (reader == NULL) {
- return (vreader_id_t)-1;
- }
- return reader->id;
-}
-
-VReaderStatus
-vreader_set_id(VReader *reader, vreader_id_t id)
-{
- if (reader == NULL) {
- return VREADER_NO_CARD;
- }
- reader->id = id;
- return VREADER_OK;
-}
-
-const char *
-vreader_get_name(VReader *reader)
-{
- if (reader == NULL) {
- return NULL;
- }
- return reader->name;
-}
-
-VReaderEmul *
-vreader_get_private(VReader *reader)
-{
- return reader->reader_private;
-}
-
-static VReaderStatus
-vreader_reset(VReader *reader, VCardPower power, unsigned char *atr, int *len)
-{
- VCard *card = vreader_get_card(reader);
-
- if (card == NULL) {
- return VREADER_NO_CARD;
- }
- /*
- * clean up our state
- */
- vcard_reset(card, power);
- if (atr) {
- vcard_get_atr(card, atr, len);
- }
- vcard_free(card); /* free our reference */
- return VREADER_OK;
-}
-
-VReaderStatus
-vreader_power_on(VReader *reader, unsigned char *atr, int *len)
-{
- return vreader_reset(reader, VCARD_POWER_ON, atr, len);
-}
-
-VReaderStatus
-vreader_power_off(VReader *reader)
-{
- return vreader_reset(reader, VCARD_POWER_OFF, NULL, 0);
-}
-
-
-VReaderStatus
-vreader_xfr_bytes(VReader *reader,
- unsigned char *send_buf, int send_buf_len,
- unsigned char *receive_buf, int *receive_buf_len)
-{
- VCardAPDU *apdu;
- VCardResponse *response = NULL;
- VCardStatus card_status;
- unsigned short status;
- VCard *card = vreader_get_card(reader);
-
- if (card == NULL) {
- return VREADER_NO_CARD;
- }
-
- apdu = vcard_apdu_new(send_buf, send_buf_len, &status);
- if (apdu == NULL) {
- response = vcard_make_response(status);
- card_status = VCARD_DONE;
- } else {
- g_debug("%s: CLS=0x%x,INS=0x%x,P1=0x%x,P2=0x%x,Lc=%d,Le=%d %s",
- __func__, apdu->a_cla, apdu->a_ins, apdu->a_p1, apdu->a_p2,
- apdu->a_Lc, apdu->a_Le, apdu_ins_to_string(apdu->a_ins));
- card_status = vcard_process_apdu(card, apdu, &response);
- if (response) {
- g_debug("%s: status=%d sw1=0x%x sw2=0x%x len=%d (total=%d)",
- __func__, response->b_status, response->b_sw1,
- response->b_sw2, response->b_len, response->b_total_len);
- }
- }
- assert(card_status == VCARD_DONE && response);
- int size = MIN(*receive_buf_len, response->b_total_len);
- memcpy(receive_buf, response->b_data, size);
- *receive_buf_len = size;
- vcard_response_delete(response);
- vcard_apdu_delete(apdu);
- vcard_free(card); /* free our reference */
- return VREADER_OK;
-}
-
-struct VReaderListStruct {
- VReaderListEntry *head;
- VReaderListEntry *tail;
-};
-
-struct VReaderListEntryStruct {
- VReaderListEntry *next;
- VReaderListEntry *prev;
- VReader *reader;
-};
-
-
-static VReaderListEntry *
-vreader_list_entry_new(VReader *reader)
-{
- VReaderListEntry *new_reader_list_entry;
-
- new_reader_list_entry = g_new0(VReaderListEntry, 1);
- new_reader_list_entry->reader = vreader_reference(reader);
- return new_reader_list_entry;
-}
-
-static void
-vreader_list_entry_delete(VReaderListEntry *entry)
-{
- if (entry == NULL) {
- return;
- }
- vreader_free(entry->reader);
- g_free(entry);
-}
-
-
-static VReaderList *
-vreader_list_new(void)
-{
- VReaderList *new_reader_list;
-
- new_reader_list = g_new0(VReaderList, 1);
- return new_reader_list;
-}
-
-void
-vreader_list_delete(VReaderList *list)
-{
- VReaderListEntry *current_entry;
- VReaderListEntry *next_entry;
- for (current_entry = vreader_list_get_first(list); current_entry;
- current_entry = next_entry) {
- next_entry = vreader_list_get_next(current_entry);
- vreader_list_entry_delete(current_entry);
- }
- g_free(list);
-}
-
-
-VReaderListEntry *
-vreader_list_get_first(VReaderList *list)
-{
- return list ? list->head : NULL;
-}
-
-VReaderListEntry *
-vreader_list_get_next(VReaderListEntry *current)
-{
- return current ? current->next : NULL;
-}
-
-VReader *
-vreader_list_get_reader(VReaderListEntry *entry)
-{
- return entry ? vreader_reference(entry->reader) : NULL;
-}
-
-static void
-vreader_queue(VReaderList *list, VReaderListEntry *entry)
-{
- if (entry == NULL) {
- return;
- }
- entry->next = NULL;
- entry->prev = list->tail;
- if (list->head) {
- list->tail->next = entry;
- } else {
- list->head = entry;
- }
- list->tail = entry;
-}
-
-static void
-vreader_dequeue(VReaderList *list, VReaderListEntry *entry)
-{
- if (entry == NULL) {
- return;
- }
- if (entry->next == NULL) {
- list->tail = entry->prev;
- } else if (entry->prev == NULL) {
- list->head = entry->next;
- } else {
- entry->prev->next = entry->next;
- entry->next->prev = entry->prev;
- }
- if ((list->tail == NULL) || (list->head == NULL)) {
- list->head = list->tail = NULL;
- }
- entry->next = entry->prev = NULL;
-}
-
-static VReaderList *vreader_list;
-static CompatGMutex vreader_list_mutex;
-
-static void
-vreader_list_init(void)
-{
- vreader_list = vreader_list_new();
-}
-
-static void
-vreader_list_lock(void)
-{
- g_mutex_lock(&vreader_list_mutex);
-}
-
-static void
-vreader_list_unlock(void)
-{
- g_mutex_unlock(&vreader_list_mutex);
-}
-
-static VReaderList *
-vreader_copy_list(VReaderList *list)
-{
- VReaderList *new_list;
- VReaderListEntry *current_entry;
-
- new_list = vreader_list_new();
- if (new_list == NULL) {
- return NULL;
- }
- for (current_entry = vreader_list_get_first(list); current_entry;
- current_entry = vreader_list_get_next(current_entry)) {
- VReader *reader = vreader_list_get_reader(current_entry);
- VReaderListEntry *new_entry = vreader_list_entry_new(reader);
-
- vreader_free(reader);
- vreader_queue(new_list, new_entry);
- }
- return new_list;
-}
-
-VReaderList *
-vreader_get_reader_list(void)
-{
- VReaderList *new_reader_list;
-
- vreader_list_lock();
- new_reader_list = vreader_copy_list(vreader_list);
- vreader_list_unlock();
- return new_reader_list;
-}
-
-VReader *
-vreader_get_reader_by_id(vreader_id_t id)
-{
- VReader *reader = NULL;
- VReaderListEntry *current_entry;
-
- if (id == (vreader_id_t) -1) {
- return NULL;
- }
-
- vreader_list_lock();
- for (current_entry = vreader_list_get_first(vreader_list); current_entry;
- current_entry = vreader_list_get_next(current_entry)) {
- VReader *creader = vreader_list_get_reader(current_entry);
- if (creader->id == id) {
- reader = creader;
- break;
- }
- vreader_free(creader);
- }
- vreader_list_unlock();
- return reader;
-}
-
-VReader *
-vreader_get_reader_by_name(const char *name)
-{
- VReader *reader = NULL;
- VReaderListEntry *current_entry;
-
- vreader_list_lock();
- for (current_entry = vreader_list_get_first(vreader_list); current_entry;
- current_entry = vreader_list_get_next(current_entry)) {
- VReader *creader = vreader_list_get_reader(current_entry);
- if (strcmp(creader->name, name) == 0) {
- reader = creader;
- break;
- }
- vreader_free(creader);
- }
- vreader_list_unlock();
- return reader;
-}
-
-/* called from card_emul to initialize the readers */
-VReaderStatus
-vreader_add_reader(VReader *reader)
-{
- VReaderListEntry *reader_entry;
-
- reader_entry = vreader_list_entry_new(reader);
- if (reader_entry == NULL) {
- return VREADER_OUT_OF_MEMORY;
- }
- vreader_list_lock();
- vreader_queue(vreader_list, reader_entry);
- vreader_list_unlock();
- vevent_queue_vevent(vevent_new(VEVENT_READER_INSERT, reader, NULL));
- return VREADER_OK;
-}
-
-
-VReaderStatus
-vreader_remove_reader(VReader *reader)
-{
- VReaderListEntry *current_entry;
-
- vreader_list_lock();
- for (current_entry = vreader_list_get_first(vreader_list); current_entry;
- current_entry = vreader_list_get_next(current_entry)) {
- if (current_entry->reader == reader) {
- break;
- }
- }
- vreader_dequeue(vreader_list, current_entry);
- vreader_list_unlock();
- vreader_list_entry_delete(current_entry);
- vevent_queue_vevent(vevent_new(VEVENT_READER_REMOVE, reader, NULL));
- return VREADER_OK;
-}
-
-/*
- * Generate VEVENT_CARD_INSERT or VEVENT_CARD_REMOVE based on vreader
- * state. Separated from vreader_insert_card to allow replaying events
- * for a given state.
- */
-void
-vreader_queue_card_event(VReader *reader)
-{
- vevent_queue_vevent(vevent_new(
- reader->card ? VEVENT_CARD_INSERT : VEVENT_CARD_REMOVE, reader,
- reader->card));
-}
-
-/*
- * insert/remove a new card. for removal, card == NULL
- */
-VReaderStatus
-vreader_insert_card(VReader *reader, VCard *card)
-{
- vreader_lock(reader);
- if (reader->card) {
- /* decrement reference count */
- vcard_free(reader->card);
- reader->card = NULL;
- }
- reader->card = vcard_reference(card);
- vreader_unlock(reader);
- vreader_queue_card_event(reader);
- return VREADER_OK;
-}
-
-/*
- * initialize all the static reader structures
- */
-void
-vreader_init(void)
-{
- vreader_list_init();
-}
-
diff --git a/libcacard/vreader.h b/libcacard/vreader.h
deleted file mode 100644
index ec2042136c..0000000000
--- a/libcacard/vreader.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
- * See the COPYING.LIB file in the top-level directory.
- */
-
-#ifndef VREADER_H
-#define VREADER_H 1
-
-#include "eventt.h"
-#include "vreadert.h"
-#include "vcardt.h"
-
-/*
- * calls for reader front end
- */
-VReaderStatus vreader_power_on(VReader *reader, unsigned char *atr, int *len);
-VReaderStatus vreader_power_off(VReader *reader);
-VReaderStatus vreader_xfr_bytes(VReader *reader, unsigned char *send_buf,
- int send_buf_len, unsigned char *receive_buf,
- int *receive_buf_len);
-
-/* constructor */
-VReader *vreader_new(const char *readerName, VReaderEmul *emul_private,
- VReaderEmulFree private_free);
-/* get a new reference to a reader */
-VReader *vreader_reference(VReader *reader);
-/* "destructor" (readers are reference counted) */
-void vreader_free(VReader *reader);
-
-/* accessors */
-VReaderEmul *vreader_get_private(VReader *);
-VReaderStatus vreader_card_is_present(VReader *reader);
-void vreader_queue_card_event(VReader *reader);
-const char *vreader_get_name(VReader *reader);
-vreader_id_t vreader_get_id(VReader *reader);
-VReaderStatus vreader_set_id(VReader *reader, vreader_id_t id);
-
-/* list operations */
-VReaderList *vreader_get_reader_list(void);
-void vreader_list_delete(VReaderList *list);
-VReader *vreader_list_get_reader(VReaderListEntry *entry);
-VReaderListEntry *vreader_list_get_first(VReaderList *list);
-VReaderListEntry *vreader_list_get_next(VReaderListEntry *list);
-VReader *vreader_get_reader_by_id(vreader_id_t id);
-VReader *vreader_get_reader_by_name(const char *name);
-
-/*
- * list tools for vcard_emul
- */
-void vreader_init(void);
-VReaderStatus vreader_add_reader(VReader *reader);
-VReaderStatus vreader_remove_reader(VReader *reader);
-VReaderStatus vreader_insert_card(VReader *reader, VCard *card);
-
-#endif
diff --git a/libcacard/vreadert.h b/libcacard/vreadert.h
deleted file mode 100644
index f97e0a79ec..0000000000
--- a/libcacard/vreadert.h
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
- * See the COPYING.LIB file in the top-level directory.
- */
-
-#ifndef VREADERT_H
-#define VREADERT_H 1
-
-typedef enum {
- VREADER_OK = 0,
- VREADER_NO_CARD,
- VREADER_OUT_OF_MEMORY
-} VReaderStatus;
-
-typedef unsigned int vreader_id_t;
-typedef struct VReaderStruct VReader;
-typedef struct VReaderListStruct VReaderList;
-typedef struct VReaderListEntryStruct VReaderListEntry;
-
-typedef struct VReaderEmulStruct VReaderEmul;
-typedef void (*VReaderEmulFree)(VReaderEmul *);
-
-#endif
-
diff --git a/libcacard/vscard_common.h b/libcacard/vscard_common.h
deleted file mode 100644
index 08f68e4dd2..0000000000
--- a/libcacard/vscard_common.h
+++ /dev/null
@@ -1,178 +0,0 @@
-/* Virtual Smart Card protocol definition
- *
- * This protocol is between a host using virtual smart card readers,
- * and a client providing the smart cards, perhaps by emulating them or by
- * access to real cards.
- *
- * Definitions for this protocol:
- * Host - user of the card
- * Client - owner of the card
- *
- * The current implementation passes the raw APDU's from 7816 and additionally
- * contains messages to setup and teardown readers, handle insertion and
- * removal of cards, negotiate the protocol via capabilities and provide
- * for error responses.
- *
- * Copyright (c) 2011 Red Hat.
- *
- * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
- * See the COPYING.LIB file in the top-level directory.
- */
-
-#ifndef VSCARD_COMMON_H
-#define VSCARD_COMMON_H
-
-#include <stdint.h>
-
-#define VERSION_MAJOR_BITS 11
-#define VERSION_MIDDLE_BITS 11
-#define VERSION_MINOR_BITS 10
-
-#define MAKE_VERSION(major, middle, minor) \
- ((major << (VERSION_MINOR_BITS + VERSION_MIDDLE_BITS)) \
- | (middle << VERSION_MINOR_BITS) \
- | (minor))
-
-/*
- * IMPORTANT NOTE on VERSION
- *
- * The version below MUST be changed whenever a change in this file is made.
- *
- * The last digit, the minor, is for bug fix changes only.
- *
- * The middle digit is for backward / forward compatible changes, updates
- * to the existing messages, addition of fields.
- *
- * The major digit is for a breaking change of protocol, presumably
- * something that cannot be accommodated with the existing protocol.
- */
-
-#define VSCARD_VERSION MAKE_VERSION(0, 0, 2)
-
-typedef enum VSCMsgType {
- VSC_Init = 1,
- VSC_Error,
- VSC_ReaderAdd,
- VSC_ReaderRemove,
- VSC_ATR,
- VSC_CardRemove,
- VSC_APDU,
- VSC_Flush,
- VSC_FlushComplete
-} VSCMsgType;
-
-typedef enum VSCErrorCode {
- VSC_SUCCESS = 0,
- VSC_GENERAL_ERROR = 1,
- VSC_CANNOT_ADD_MORE_READERS,
- VSC_CARD_ALREAY_INSERTED,
-} VSCErrorCode;
-
-#define VSCARD_UNDEFINED_READER_ID 0xffffffff
-#define VSCARD_MINIMAL_READER_ID 0
-
-#define VSCARD_MAGIC (*(uint32_t *)"VSCD")
-
-/*
- * Header
- * Each message starts with the header.
- * type - message type
- * reader_id - used by messages that are reader specific
- * length - length of payload (not including header, i.e. zero for
- * messages containing empty payloads)
- */
-typedef struct VSCMsgHeader {
- uint32_t type;
- uint32_t reader_id;
- uint32_t length;
- uint8_t data[0];
-} VSCMsgHeader;
-
-/*
- * VSCMsgInit Client <-> Host
- * Client sends it on connection, with its own capabilities.
- * Host replies with VSCMsgInit filling in its capabilities.
- *
- * It is not meant to be used for negotiation, i.e. sending more then
- * once from any side, but could be used for that in the future.
- */
-typedef struct VSCMsgInit {
- uint32_t magic;
- uint32_t version;
- uint32_t capabilities[1]; /* receiver must check length,
- array may grow in the future*/
-} VSCMsgInit;
-
-/*
- * VSCMsgError Client <-> Host
- * This message is a response to any of:
- * Reader Add
- * Reader Remove
- * Card Remove
- * If the operation was successful then VSC_SUCCESS
- * is returned, other wise a specific error code.
- */
-typedef struct VSCMsgError {
- uint32_t code;
-} VSCMsgError;
-
-/*
- * VSCMsgReaderAdd Client -> Host
- * Host replies with allocated reader id in VSCMsgError with code==SUCCESS.
- *
- * name - name of the reader on client side, UTF-8 encoded. Only used
- * for client presentation (may be translated to the device presented to the
- * guest), protocol wise only reader_id is important.
- */
-typedef struct VSCMsgReaderAdd {
- uint8_t name[0];
-} VSCMsgReaderAdd;
-
-/*
- * VSCMsgReaderRemove Client -> Host
- * The client's reader has been removed.
- */
-typedef struct VSCMsgReaderRemove {
-} VSCMsgReaderRemove;
-
-/*
- * VSCMsgATR Client -> Host
- * Answer to reset. Sent for card insertion or card reset. The reset/insertion
- * happens on the client side, they do not require any action from the host.
- */
-typedef struct VSCMsgATR {
- uint8_t atr[0];
-} VSCMsgATR;
-
-/*
- * VSCMsgCardRemove Client -> Host
- * The client card has been removed.
- */
-typedef struct VSCMsgCardRemove {
-} VSCMsgCardRemove;
-
-/*
- * VSCMsgAPDU Client <-> Host
- * Main reason of existence. Transfer a single APDU in either direction.
- */
-typedef struct VSCMsgAPDU {
- uint8_t data[0];
-} VSCMsgAPDU;
-
-/*
- * VSCMsgFlush Host -> Client
- * Request client to send a FlushComplete message when it is done
- * servicing all outstanding APDUs
- */
-typedef struct VSCMsgFlush {
-} VSCMsgFlush;
-
-/*
- * VSCMsgFlush Client -> Host
- * Client response to Flush after all APDUs have been processed and
- * responses sent.
- */
-typedef struct VSCMsgFlushComplete {
-} VSCMsgFlushComplete;
-
-#endif /* VSCARD_COMMON_H */
diff --git a/libcacard/vscclient.c b/libcacard/vscclient.c
deleted file mode 100644
index 0652684437..0000000000
--- a/libcacard/vscclient.c
+++ /dev/null
@@ -1,785 +0,0 @@
-/*
- * Tester for VSCARD protocol, client side.
- *
- * Can be used with ccid-card-passthru.
- *
- * Copyright (c) 2011 Red Hat.
- * Written by Alon Levy.
- *
- * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
- * See the COPYING.LIB file in the top-level directory.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#ifndef _WIN32
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <netdb.h>
-#include <unistd.h>
-#define closesocket(x) close(x)
-#else
-#include <getopt.h>
-#endif
-
-#include "glib-compat.h"
-
-#include "vscard_common.h"
-
-#include "vreader.h"
-#include "vcard_emul.h"
-#include "vevent.h"
-
-static int verbose;
-
-static void
-print_byte_array(
- uint8_t *arrBytes,
- unsigned int nSize
-) {
- int i;
- for (i = 0; i < nSize; i++) {
- printf("%02X ", arrBytes[i]);
- }
- printf("\n");
-}
-
-static void
-print_usage(void) {
- printf("vscclient [-c <certname> .. -e <emul_args> -d <level>%s] "
- "<host> <port>\n",
-#ifdef USE_PASSTHRU
- " -p");
- printf(" -p use passthrough mode\n");
-#else
- "");
-#endif
- vcard_emul_usage();
-}
-
-static GIOChannel *channel_socket;
-static GByteArray *socket_to_send;
-static CompatGMutex socket_to_send_lock;
-static guint socket_tag;
-
-static void
-update_socket_watch(void);
-
-static gboolean
-do_socket_send(GIOChannel *source,
- GIOCondition condition,
- gpointer data)
-{
- gsize bw;
- GError *err = NULL;
-
- g_return_val_if_fail(socket_to_send->len != 0, FALSE);
- g_return_val_if_fail(condition & G_IO_OUT, FALSE);
-
- g_io_channel_write_chars(channel_socket,
- (gchar *)socket_to_send->data, socket_to_send->len, &bw, &err);
- if (err != NULL) {
- g_error("Error while sending socket %s", err->message);
- return FALSE;
- }
- g_byte_array_remove_range(socket_to_send, 0, bw);
-
- if (socket_to_send->len == 0) {
- update_socket_watch();
- return FALSE;
- }
- return TRUE;
-}
-
-static gboolean
-socket_prepare_sending(gpointer user_data)
-{
- update_socket_watch();
-
- return FALSE;
-}
-
-static int
-send_msg(
- VSCMsgType type,
- uint32_t reader_id,
- const void *msg,
- unsigned int length
-) {
- VSCMsgHeader mhHeader;
-
- g_mutex_lock(&socket_to_send_lock);
-
- if (verbose > 10) {
- printf("sending type=%d id=%u, len =%u (0x%x)\n",
- type, reader_id, length, length);
- }
-
- mhHeader.type = htonl(type);
- mhHeader.reader_id = 0;
- mhHeader.length = htonl(length);
- g_byte_array_append(socket_to_send, (guint8 *)&mhHeader, sizeof(mhHeader));
- g_byte_array_append(socket_to_send, (guint8 *)msg, length);
- g_idle_add(socket_prepare_sending, NULL);
-
- g_mutex_unlock(&socket_to_send_lock);
-
- return 0;
-}
-
-static VReader *pending_reader;
-static CompatGMutex pending_reader_lock;
-static CompatGCond pending_reader_condition;
-
-#define MAX_ATR_LEN 40
-static gpointer
-event_thread(gpointer arg)
-{
- unsigned char atr[MAX_ATR_LEN];
- int atr_len;
- VEvent *event;
- unsigned int reader_id;
-
-
- while (1) {
- const char *reader_name;
-
- event = vevent_wait_next_vevent();
- if (event == NULL) {
- break;
- }
- reader_id = vreader_get_id(event->reader);
- if (reader_id == VSCARD_UNDEFINED_READER_ID &&
- event->type != VEVENT_READER_INSERT) {
- /* ignore events from readers qemu has rejected */
- /* if qemu is still deciding on this reader, wait to see if need to
- * forward this event */
- g_mutex_lock(&pending_reader_lock);
- if (!pending_reader || (pending_reader != event->reader)) {
- /* wasn't for a pending reader, this reader has already been
- * rejected by qemu */
- g_mutex_unlock(&pending_reader_lock);
- vevent_delete(event);
- continue;
- }
- /* this reader hasn't been told its status from qemu yet, wait for
- * that status */
- while (pending_reader != NULL) {
- g_cond_wait(&pending_reader_condition, &pending_reader_lock);
- }
- g_mutex_unlock(&pending_reader_lock);
- /* now recheck the id */
- reader_id = vreader_get_id(event->reader);
- if (reader_id == VSCARD_UNDEFINED_READER_ID) {
- /* this reader was rejected */
- vevent_delete(event);
- continue;
- }
- /* reader was accepted, now forward the event */
- }
- switch (event->type) {
- case VEVENT_READER_INSERT:
- /* tell qemu to insert a new CCID reader */
- /* wait until qemu has responded to our first reader insert
- * before we send a second. That way we won't confuse the responses
- * */
- g_mutex_lock(&pending_reader_lock);
- while (pending_reader != NULL) {
- g_cond_wait(&pending_reader_condition, &pending_reader_lock);
- }
- pending_reader = vreader_reference(event->reader);
- g_mutex_unlock(&pending_reader_lock);
- reader_name = vreader_get_name(event->reader);
- if (verbose > 10) {
- printf(" READER INSERT: %s\n", reader_name);
- }
- send_msg(VSC_ReaderAdd,
- reader_id, /* currerntly VSCARD_UNDEFINED_READER_ID */
- NULL, 0 /* TODO reader_name, strlen(reader_name) */);
- break;
- case VEVENT_READER_REMOVE:
- /* future, tell qemu that an old CCID reader has been removed */
- if (verbose > 10) {
- printf(" READER REMOVE: %u\n", reader_id);
- }
- send_msg(VSC_ReaderRemove, reader_id, NULL, 0);
- break;
- case VEVENT_CARD_INSERT:
- /* get the ATR (intended as a response to a power on from the
- * reader */
- atr_len = MAX_ATR_LEN;
- vreader_power_on(event->reader, atr, &atr_len);
- /* ATR call functions as a Card Insert event */
- if (verbose > 10) {
- printf(" CARD INSERT %u: ", reader_id);
- print_byte_array(atr, atr_len);
- }
- send_msg(VSC_ATR, reader_id, atr, atr_len);
- break;
- case VEVENT_CARD_REMOVE:
- /* Card removed */
- if (verbose > 10) {
- printf(" CARD REMOVE %u:\n", reader_id);
- }
- send_msg(VSC_CardRemove, reader_id, NULL, 0);
- break;
- default:
- break;
- }
- vevent_delete(event);
- }
- return NULL;
-}
-
-
-static unsigned int
-get_id_from_string(char *string, unsigned int default_id)
-{
- unsigned int id = atoi(string);
-
- /* don't accidentally swith to zero because no numbers have been supplied */
- if ((id == 0) && *string != '0') {
- return default_id;
- }
- return id;
-}
-
-static int
-on_host_init(VSCMsgHeader *mhHeader, VSCMsgInit *incoming)
-{
- uint32_t *capabilities = (incoming->capabilities);
- int num_capabilities =
- 1 + ((mhHeader->length - sizeof(VSCMsgInit)) / sizeof(uint32_t));
- int i;
-
- incoming->version = ntohl(incoming->version);
- if (incoming->version != VSCARD_VERSION) {
- if (verbose > 0) {
- printf("warning: host has version %d, we have %d\n",
- verbose, VSCARD_VERSION);
- }
- }
- if (incoming->magic != VSCARD_MAGIC) {
- printf("unexpected magic: got %d, expected %d\n",
- incoming->magic, VSCARD_MAGIC);
- return -1;
- }
- for (i = 0 ; i < num_capabilities; ++i) {
- capabilities[i] = ntohl(capabilities[i]);
- }
- /* Future: check capabilities */
- /* remove whatever reader might be left in qemu,
- * in case of an unclean previous exit. */
- send_msg(VSC_ReaderRemove, VSCARD_MINIMAL_READER_ID, NULL, 0);
- /* launch the event_thread. This will trigger reader adds for all the
- * existing readers */
- g_thread_new("vsc/event", event_thread, NULL);
- return 0;
-}
-
-
-enum {
- STATE_HEADER,
- STATE_MESSAGE,
-};
-
-#define APDUBufSize 270
-
-static gboolean
-do_socket_read(GIOChannel *source,
- GIOCondition condition,
- gpointer data)
-{
- int rv;
- int dwSendLength;
- int dwRecvLength;
- uint8_t pbRecvBuffer[APDUBufSize];
- static uint8_t pbSendBuffer[APDUBufSize];
- VReaderStatus reader_status;
- VReader *reader = NULL;
- static VSCMsgHeader mhHeader;
- VSCMsgError *error_msg;
- GError *err = NULL;
-
- static gchar *buf;
- static gsize br, to_read;
- static int state = STATE_HEADER;
-
- if (state == STATE_HEADER && to_read == 0) {
- buf = (gchar *)&mhHeader;
- to_read = sizeof(mhHeader);
- }
-
- if (to_read > 0) {
- g_io_channel_read_chars(source, (gchar *)buf, to_read, &br, &err);
- if (err != NULL) {
- g_error("error while reading: %s", err->message);
- }
- buf += br;
- to_read -= br;
- if (to_read != 0) {
- return TRUE;
- }
- }
-
- if (state == STATE_HEADER) {
- mhHeader.type = ntohl(mhHeader.type);
- mhHeader.reader_id = ntohl(mhHeader.reader_id);
- mhHeader.length = ntohl(mhHeader.length);
- if (verbose) {
- printf("Header: type=%d, reader_id=%u length=%d (0x%x)\n",
- mhHeader.type, mhHeader.reader_id, mhHeader.length,
- mhHeader.length);
- }
- switch (mhHeader.type) {
- case VSC_APDU:
- case VSC_Flush:
- case VSC_Error:
- case VSC_Init:
- buf = (gchar *)pbSendBuffer;
- to_read = mhHeader.length;
- state = STATE_MESSAGE;
- return TRUE;
- default:
- fprintf(stderr, "Unexpected message of type 0x%X\n", mhHeader.type);
- return FALSE;
- }
- }
-
- if (state == STATE_MESSAGE) {
- switch (mhHeader.type) {
- case VSC_APDU:
- if (verbose) {
- printf(" recv APDU: ");
- print_byte_array(pbSendBuffer, mhHeader.length);
- }
- /* Transmit received APDU */
- dwSendLength = mhHeader.length;
- dwRecvLength = sizeof(pbRecvBuffer);
- reader = vreader_get_reader_by_id(mhHeader.reader_id);
- reader_status = vreader_xfr_bytes(reader,
- pbSendBuffer, dwSendLength,
- pbRecvBuffer, &dwRecvLength);
- if (reader_status == VREADER_OK) {
- mhHeader.length = dwRecvLength;
- if (verbose) {
- printf(" send response: ");
- print_byte_array(pbRecvBuffer, mhHeader.length);
- }
- send_msg(VSC_APDU, mhHeader.reader_id,
- pbRecvBuffer, dwRecvLength);
- } else {
- rv = reader_status; /* warning: not meaningful */
- send_msg(VSC_Error, mhHeader.reader_id, &rv, sizeof(uint32_t));
- }
- vreader_free(reader);
- reader = NULL; /* we've freed it, don't use it by accident
- again */
- break;
- case VSC_Flush:
- /* TODO: actually flush */
- send_msg(VSC_FlushComplete, mhHeader.reader_id, NULL, 0);
- break;
- case VSC_Error:
- error_msg = (VSCMsgError *) pbSendBuffer;
- if (error_msg->code == VSC_SUCCESS) {
- g_mutex_lock(&pending_reader_lock);
- if (pending_reader) {
- vreader_set_id(pending_reader, mhHeader.reader_id);
- vreader_free(pending_reader);
- pending_reader = NULL;
- g_cond_signal(&pending_reader_condition);
- }
- g_mutex_unlock(&pending_reader_lock);
- break;
- }
- printf("warning: qemu refused to add reader\n");
- if (error_msg->code == VSC_CANNOT_ADD_MORE_READERS) {
- /* clear pending reader, qemu can't handle any more */
- g_mutex_lock(&pending_reader_lock);
- if (pending_reader) {
- pending_reader = NULL;
- /* make sure the event loop doesn't hang */
- g_cond_signal(&pending_reader_condition);
- }
- g_mutex_unlock(&pending_reader_lock);
- }
- break;
- case VSC_Init:
- if (on_host_init(&mhHeader, (VSCMsgInit *)pbSendBuffer) < 0) {
- return FALSE;
- }
- break;
- default:
- g_assert_not_reached();
- return FALSE;
- }
-
- state = STATE_HEADER;
- }
-
-
- return TRUE;
-}
-
-static gboolean
-do_socket(GIOChannel *source,
- GIOCondition condition,
- gpointer data)
-{
- /* not sure if two watches work well with a single win32 sources */
- if (condition & G_IO_OUT) {
- if (!do_socket_send(source, condition, data)) {
- return FALSE;
- }
- }
-
- if (condition & G_IO_IN) {
- if (!do_socket_read(source, condition, data)) {
- return FALSE;
- }
- }
-
- return TRUE;
-}
-
-static void
-update_socket_watch(void)
-{
- gboolean out = socket_to_send->len > 0;
-
- if (socket_tag != 0) {
- g_source_remove(socket_tag);
- }
-
- socket_tag = g_io_add_watch(channel_socket,
- G_IO_IN | (out ? G_IO_OUT : 0), do_socket, NULL);
-}
-
-static gboolean
-do_command(GIOChannel *source,
- GIOCondition condition,
- gpointer data)
-{
- char *string;
- VCardEmulError error;
- static unsigned int default_reader_id;
- unsigned int reader_id;
- VReader *reader = NULL;
- GError *err = NULL;
-
- g_assert(condition & G_IO_IN);
-
- reader_id = default_reader_id;
- g_io_channel_read_line(source, &string, NULL, NULL, &err);
- if (err != NULL) {
- g_error("Error while reading command: %s", err->message);
- }
-
- if (string != NULL) {
- if (strncmp(string, "exit", 4) == 0) {
- /* remove all the readers */
- VReaderList *list = vreader_get_reader_list();
- VReaderListEntry *reader_entry;
- printf("Active Readers:\n");
- for (reader_entry = vreader_list_get_first(list); reader_entry;
- reader_entry = vreader_list_get_next(reader_entry)) {
- VReader *reader = vreader_list_get_reader(reader_entry);
- vreader_id_t reader_id;
- reader_id = vreader_get_id(reader);
- if (reader_id == -1) {
- continue;
- }
- /* be nice and signal card removal first (qemu probably should
- * do this itself) */
- if (vreader_card_is_present(reader) == VREADER_OK) {
- send_msg(VSC_CardRemove, reader_id, NULL, 0);
- }
- send_msg(VSC_ReaderRemove, reader_id, NULL, 0);
- }
- exit(0);
- } else if (strncmp(string, "insert", 6) == 0) {
- if (string[6] == ' ') {
- reader_id = get_id_from_string(&string[7], reader_id);
- }
- reader = vreader_get_reader_by_id(reader_id);
- if (reader != NULL) {
- error = vcard_emul_force_card_insert(reader);
- printf("insert %s, returned %d\n",
- vreader_get_name(reader), error);
- } else {
- printf("no reader by id %u found\n", reader_id);
- }
- } else if (strncmp(string, "remove", 6) == 0) {
- if (string[6] == ' ') {
- reader_id = get_id_from_string(&string[7], reader_id);
- }
- reader = vreader_get_reader_by_id(reader_id);
- if (reader != NULL) {
- error = vcard_emul_force_card_remove(reader);
- printf("remove %s, returned %d\n",
- vreader_get_name(reader), error);
- } else {
- printf("no reader by id %u found\n", reader_id);
- }
- } else if (strncmp(string, "select", 6) == 0) {
- if (string[6] == ' ') {
- reader_id = get_id_from_string(&string[7],
- VSCARD_UNDEFINED_READER_ID);
- }
- if (reader_id != VSCARD_UNDEFINED_READER_ID) {
- reader = vreader_get_reader_by_id(reader_id);
- }
- if (reader) {
- printf("Selecting reader %u, %s\n", reader_id,
- vreader_get_name(reader));
- default_reader_id = reader_id;
- } else {
- printf("Reader with id %u not found\n", reader_id);
- }
- } else if (strncmp(string, "debug", 5) == 0) {
- if (string[5] == ' ') {
- verbose = get_id_from_string(&string[6], 0);
- }
- printf("debug level = %d\n", verbose);
- } else if (strncmp(string, "list", 4) == 0) {
- VReaderList *list = vreader_get_reader_list();
- VReaderListEntry *reader_entry;
- printf("Active Readers:\n");
- for (reader_entry = vreader_list_get_first(list); reader_entry;
- reader_entry = vreader_list_get_next(reader_entry)) {
- VReader *reader = vreader_list_get_reader(reader_entry);
- vreader_id_t reader_id;
- reader_id = vreader_get_id(reader);
- if (reader_id == -1) {
- continue;
- }
- printf("%3u %s %s\n", reader_id,
- vreader_card_is_present(reader) == VREADER_OK ?
- "CARD_PRESENT" : " ",
- vreader_get_name(reader));
- }
- printf("Inactive Readers:\n");
- for (reader_entry = vreader_list_get_first(list); reader_entry;
- reader_entry = vreader_list_get_next(reader_entry)) {
- VReader *reader = vreader_list_get_reader(reader_entry);
- vreader_id_t reader_id;
- reader_id = vreader_get_id(reader);
- if (reader_id != -1) {
- continue;
- }
-
- printf("INA %s %s\n",
- vreader_card_is_present(reader) == VREADER_OK ?
- "CARD_PRESENT" : " ",
- vreader_get_name(reader));
- }
- vreader_list_delete(list);
- } else if (*string != 0) {
- printf("valid commands:\n");
- printf("insert [reader_id]\n");
- printf("remove [reader_id]\n");
- printf("select reader_id\n");
- printf("list\n");
- printf("debug [level]\n");
- printf("exit\n");
- }
- }
- vreader_free(reader);
- printf("> ");
- fflush(stdout);
-
- return TRUE;
-}
-
-
-/* just for ease of parsing command line arguments. */
-#define MAX_CERTS 100
-
-static int
-connect_to_qemu(
- const char *host,
- const char *port
-) {
- struct addrinfo hints;
- struct addrinfo *server = NULL;
- int ret, sock;
-
- sock = socket(AF_INET, SOCK_STREAM, 0);
- if (sock < 0) {
- /* Error */
- fprintf(stderr, "Error opening socket!\n");
- return -1;
- }
-
- memset(&hints, 0, sizeof(struct addrinfo));
- hints.ai_family = AF_UNSPEC;
- hints.ai_socktype = SOCK_STREAM;
- hints.ai_flags = 0;
- hints.ai_protocol = 0; /* Any protocol */
-
- ret = getaddrinfo(host, port, &hints, &server);
-
- if (ret != 0) {
- /* Error */
- fprintf(stderr, "getaddrinfo failed\n");
- goto cleanup_socket;
- }
-
- if (connect(sock, server->ai_addr, server->ai_addrlen) < 0) {
- /* Error */
- fprintf(stderr, "Could not connect\n");
- goto cleanup_socket;
- }
- if (verbose) {
- printf("Connected (sizeof Header=%zd)!\n", sizeof(VSCMsgHeader));
- }
-
- freeaddrinfo(server);
- return sock;
-
-cleanup_socket:
- if (server) {
- freeaddrinfo(server);
- }
- closesocket(sock);
- return -1;
-}
-
-int
-main(
- int argc,
- char *argv[]
-) {
- GMainLoop *loop;
- GIOChannel *channel_stdin;
- char *qemu_host;
- char *qemu_port;
-
- VCardEmulOptions *command_line_options = NULL;
-
- char *cert_names[MAX_CERTS];
- char *emul_args = NULL;
- int cert_count = 0;
- int c, sock;
-
-#ifdef _WIN32
- WSADATA Data;
-
- if (WSAStartup(MAKEWORD(2, 2), &Data) != 0) {
- c = WSAGetLastError();
- fprintf(stderr, "WSAStartup: %d\n", c);
- return 1;
- }
-#endif
-#if !GLIB_CHECK_VERSION(2, 31, 0)
- if (!g_thread_supported()) {
- g_thread_init(NULL);
- }
-#endif
-
- while ((c = getopt(argc, argv, "c:e:pd:")) != -1) {
- switch (c) {
- case 'c':
- if (cert_count >= MAX_CERTS) {
- printf("too many certificates (max = %d)\n", MAX_CERTS);
- exit(5);
- }
- cert_names[cert_count++] = optarg;
- break;
- case 'e':
- emul_args = optarg;
- break;
- case 'p':
- print_usage();
- exit(4);
- break;
- case 'd':
- verbose = get_id_from_string(optarg, 1);
- break;
- }
- }
-
- if (argc - optind != 2) {
- print_usage();
- exit(4);
- }
-
- if (cert_count > 0) {
- char *new_args;
- int len, i;
- /* if we've given some -c options, we clearly we want do so some
- * software emulation. add that emulation now. this is NSS Emulator
- * specific */
- if (emul_args == NULL) {
- emul_args = (char *)"db=\"/etc/pki/nssdb\"";
- }
-#define SOFT_STRING ",soft=(,Virtual Reader,CAC,,"
- /* 2 == close paren & null */
- len = strlen(emul_args) + strlen(SOFT_STRING) + 2;
- for (i = 0; i < cert_count; i++) {
- len += strlen(cert_names[i])+1; /* 1 == comma */
- }
- new_args = g_malloc(len);
- strcpy(new_args, emul_args);
- strcat(new_args, SOFT_STRING);
- for (i = 0; i < cert_count; i++) {
- strcat(new_args, cert_names[i]);
- strcat(new_args, ",");
- }
- strcat(new_args, ")");
- emul_args = new_args;
- }
- if (emul_args) {
- command_line_options = vcard_emul_options(emul_args);
- }
-
- qemu_host = g_strdup(argv[argc - 2]);
- qemu_port = g_strdup(argv[argc - 1]);
- sock = connect_to_qemu(qemu_host, qemu_port);
- if (sock == -1) {
- fprintf(stderr, "error opening socket, exiting.\n");
- exit(5);
- }
-
- socket_to_send = g_byte_array_new();
- vcard_emul_init(command_line_options);
- loop = g_main_loop_new(NULL, TRUE);
-
- printf("> ");
- fflush(stdout);
-
-#ifdef _WIN32
- channel_stdin = g_io_channel_win32_new_fd(STDIN_FILENO);
-#else
- channel_stdin = g_io_channel_unix_new(STDIN_FILENO);
-#endif
- g_io_add_watch(channel_stdin, G_IO_IN, do_command, NULL);
-#ifdef _WIN32
- channel_socket = g_io_channel_win32_new_socket(sock);
-#else
- channel_socket = g_io_channel_unix_new(sock);
-#endif
- g_io_channel_set_encoding(channel_socket, NULL, NULL);
- /* we buffer ourself for thread safety reasons */
- g_io_channel_set_buffered(channel_socket, FALSE);
-
- /* Send init message, Host responds (and then we send reader attachments) */
- VSCMsgInit init = {
- .version = htonl(VSCARD_VERSION),
- .magic = VSCARD_MAGIC,
- .capabilities = {0}
- };
- send_msg(VSC_Init, 0, &init, sizeof(init));
-
- g_main_loop_run(loop);
- g_main_loop_unref(loop);
-
- g_io_channel_unref(channel_stdin);
- g_io_channel_unref(channel_socket);
- g_byte_array_free(socket_to_send, TRUE);
-
- closesocket(sock);
- return 0;
-}
diff --git a/qemu.nsi b/qemu.nsi
index cc5fafd579..a20f6ef35b 100644
--- a/qemu.nsi
+++ b/qemu.nsi
@@ -139,6 +139,9 @@ Section "${PRODUCT} (required)"
; Write the uninstall keys for Windows
WriteRegStr HKLM "${UNINST_KEY}" "DisplayName" "QEMU"
+!ifdef DISPLAYVERSION
+ WriteRegStr HKLM "${UNINST_KEY}" "DisplayVersion" "${DISPLAYVERSION}"
+!endif
WriteRegStr HKLM "${UNINST_KEY}" "UninstallString" '"${UNINST_EXE}"'
WriteRegDWORD HKLM "${UNINST_KEY}" "NoModify" 1
WriteRegDWORD HKLM "${UNINST_KEY}" "NoRepair" 1
diff --git a/slirp/tcp_input.c b/slirp/tcp_input.c
index f946db8dc0..00a77b4a5f 100644
--- a/slirp/tcp_input.c
+++ b/slirp/tcp_input.c
@@ -584,7 +584,13 @@ findso:
goto cont_input;
}
- if((tcp_fconnect(so) == -1) && (errno != EINPROGRESS) && (errno != EWOULDBLOCK)) {
+ if ((tcp_fconnect(so) == -1) &&
+#if defined(_WIN32)
+ socket_error() != WSAEWOULDBLOCK
+#else
+ (errno != EINPROGRESS) && (errno != EWOULDBLOCK)
+#endif
+ ) {
u_char code=ICMP_UNREACH_NET;
DEBUG_MISC((dfd, " tcp fconnect errno = %d-%s\n",
errno,strerror(errno)));
diff --git a/target-arm/kvm.c b/target-arm/kvm.c
index b278542085..6aadcd88f7 100644
--- a/target-arm/kvm.c
+++ b/target-arm/kvm.c
@@ -585,18 +585,23 @@ void kvm_arch_init_irq_routing(KVMState *s)
int kvm_arch_irqchip_create(KVMState *s)
{
- int ret;
-
/* If we can create the VGIC using the newer device control API, we
* let the device do this when it initializes itself, otherwise we
* fall back to the old API */
+ return kvm_check_extension(s, KVM_CAP_DEVICE_CTRL);
+}
- ret = kvm_create_device(s, KVM_DEV_TYPE_ARM_VGIC_V2, true);
- if (ret == 0) {
- return 1;
+int kvm_arm_vgic_probe(void)
+{
+ if (kvm_create_device(kvm_state,
+ KVM_DEV_TYPE_ARM_VGIC_V3, true) == 0) {
+ return 3;
+ } else if (kvm_create_device(kvm_state,
+ KVM_DEV_TYPE_ARM_VGIC_V2, true) == 0) {
+ return 2;
+ } else {
+ return 0;
}
-
- return 0;
}
int kvm_arch_fixup_msi_route(struct kvm_irq_routing_entry *route,
diff --git a/target-arm/kvm_arm.h b/target-arm/kvm_arm.h
index b3e0ab7e7c..b516041779 100644
--- a/target-arm/kvm_arm.h
+++ b/target-arm/kvm_arm.h
@@ -189,6 +189,15 @@ int kvm_arm_sync_mpstate_to_kvm(ARMCPU *cpu);
*/
int kvm_arm_sync_mpstate_to_qemu(ARMCPU *cpu);
+int kvm_arm_vgic_probe(void);
+
+#else
+
+static inline int kvm_arm_vgic_probe(void)
+{
+ return 0;
+}
+
#endif
static inline const char *gic_class_name(void)
@@ -196,4 +205,14 @@ static inline const char *gic_class_name(void)
return kvm_irqchip_in_kernel() ? "kvm-arm-gic" : "arm_gic";
}
+/**
+ * gicv3_class_name
+ *
+ * Return name of GICv3 class to use depending on whether KVM acceleration is
+ * in use. May throw an error if the chosen implementation is not available.
+ *
+ * Returns: class name to use
+ */
+const char *gicv3_class_name(void);
+
#endif
diff --git a/target-arm/machine.c b/target-arm/machine.c
index 32adfe792e..36a0d159cc 100644
--- a/target-arm/machine.c
+++ b/target-arm/machine.c
@@ -1,5 +1,6 @@
#include "hw/hw.h"
#include "hw/boards.h"
+#include "qemu/error-report.h"
#include "sysemu/kvm.h"
#include "kvm_arm.h"
#include "internals.h"
@@ -328,3 +329,20 @@ const VMStateDescription vmstate_arm_cpu = {
NULL
}
};
+
+const char *gicv3_class_name(void)
+{
+ if (kvm_irqchip_in_kernel()) {
+#ifdef TARGET_AARCH64
+ return "kvm-arm-gicv3";
+#else
+ error_report("KVM GICv3 acceleration is not supported on this "
+ "platform\n");
+#endif
+ } else {
+ /* TODO: Software emulation is not implemented yet */
+ error_report("KVM is currently required for GICv3 emulation\n");
+ }
+
+ exit(1);
+}
diff --git a/ui/gtk.c b/ui/gtk.c
index 187de74b2c..3057cdc3f7 100644
--- a/ui/gtk.c
+++ b/ui/gtk.c
@@ -104,6 +104,15 @@
#define GDK_KEY_Pause GDK_Pause
#endif
+/* Some older mingw versions lack this constant or have
+ * it conditionally defined */
+#ifdef _WIN32
+# ifndef MAPVK_VK_TO_VSC
+# define MAPVK_VK_TO_VSC 0
+# endif
+#endif
+
+
#define HOTKEY_MODIFIERS (GDK_CONTROL_MASK | GDK_MOD1_MASK)
static const int modifier_keycode[] = {
diff --git a/util/oslib-win32.c b/util/oslib-win32.c
index 730a6707a0..08f5a9cda2 100644
--- a/util/oslib-win32.c
+++ b/util/oslib-win32.c
@@ -95,6 +95,7 @@ void qemu_anon_ram_free(void *ptr, size_t size)
}
}
+#ifndef CONFIG_LOCALTIME_R
/* FIXME: add proper locking */
struct tm *gmtime_r(const time_t *timep, struct tm *result)
{
@@ -118,6 +119,7 @@ struct tm *localtime_r(const time_t *timep, struct tm *result)
}
return p;
}
+#endif /* CONFIG_LOCALTIME_R */
void qemu_set_block(int fd)
{
diff --git a/util/qemu-thread-win32.c b/util/qemu-thread-win32.c
index 406b52f91d..6cdd553e9a 100644
--- a/util/qemu-thread-win32.c
+++ b/util/qemu-thread-win32.c
@@ -238,10 +238,34 @@ void qemu_sem_wait(QemuSemaphore *sem)
}
}
+/* Wrap a Win32 manual-reset event with a fast userspace path. The idea
+ * is to reset the Win32 event lazily, as part of a test-reset-test-wait
+ * sequence. Such a sequence is, indeed, how QemuEvents are used by
+ * RCU and other subsystems!
+ *
+ * Valid transitions:
+ * - free->set, when setting the event
+ * - busy->set, when setting the event, followed by futex_wake
+ * - set->free, when resetting the event
+ * - free->busy, when waiting
+ *
+ * set->busy does not happen (it can be observed from the outside but
+ * it really is set->free->busy).
+ *
+ * busy->free provably cannot happen; to enforce it, the set->free transition
+ * is done with an OR, which becomes a no-op if the event has concurrently
+ * transitioned to free or busy (and is faster than cmpxchg).
+ */
+
+#define EV_SET 0
+#define EV_FREE 1
+#define EV_BUSY -1
+
void qemu_event_init(QemuEvent *ev, bool init)
{
/* Manual reset. */
- ev->event = CreateEvent(NULL, TRUE, init, NULL);
+ ev->event = CreateEvent(NULL, TRUE, TRUE, NULL);
+ ev->value = (init ? EV_SET : EV_FREE);
}
void qemu_event_destroy(QemuEvent *ev)
@@ -251,17 +275,51 @@ void qemu_event_destroy(QemuEvent *ev)
void qemu_event_set(QemuEvent *ev)
{
- SetEvent(ev->event);
+ if (atomic_mb_read(&ev->value) != EV_SET) {
+ if (atomic_xchg(&ev->value, EV_SET) == EV_BUSY) {
+ /* There were waiters, wake them up. */
+ SetEvent(ev->event);
+ }
+ }
}
void qemu_event_reset(QemuEvent *ev)
{
- ResetEvent(ev->event);
+ if (atomic_mb_read(&ev->value) == EV_SET) {
+ /* If there was a concurrent reset (or even reset+wait),
+ * do nothing. Otherwise change EV_SET->EV_FREE.
+ */
+ atomic_or(&ev->value, EV_FREE);
+ }
}
void qemu_event_wait(QemuEvent *ev)
{
- WaitForSingleObject(ev->event, INFINITE);
+ unsigned value;
+
+ value = atomic_mb_read(&ev->value);
+ if (value != EV_SET) {
+ if (value == EV_FREE) {
+ /* qemu_event_set is not yet going to call SetEvent, but we are
+ * going to do another check for EV_SET below when setting EV_BUSY.
+ * At that point it is safe to call WaitForSingleObject.
+ */
+ ResetEvent(ev->event);
+
+ /* Tell qemu_event_set that there are waiters. No need to retry
+ * because there cannot be a concurent busy->free transition.
+ * After the CAS, the event will be either set or busy.
+ */
+ if (atomic_cmpxchg(&ev->value, EV_FREE, EV_BUSY) == EV_SET) {
+ value = EV_SET;
+ } else {
+ value = EV_BUSY;
+ }
+ }
+ if (value == EV_BUSY) {
+ WaitForSingleObject(ev->event, INFINITE);
+ }
+ }
}
struct QemuThreadData {