diff --git a/OVMFbin/OVMF_CODE-pure-efi.fd b/OVMFbin/OVMF_CODE-pure-efi.fd new file mode 100644 index 0000000..8f5bad0 Binary files /dev/null and b/OVMFbin/OVMF_CODE-pure-efi.fd differ diff --git a/OVMFbin/OVMF_VARS-pure-efi.fd b/OVMFbin/OVMF_VARS-pure-efi.fd new file mode 100644 index 0000000..2f18240 Binary files /dev/null and b/OVMFbin/OVMF_VARS-pure-efi.fd differ diff --git a/OVMFbin/git folder/COMMIT_EDITMSG b/OVMFbin/git folder/COMMIT_EDITMSG new file mode 100644 index 0000000..9ed8903 --- /dev/null +++ b/OVMFbin/git folder/COMMIT_EDITMSG @@ -0,0 +1,11 @@ +load kernel with bootloader +# Please enter the commit message for your changes. Lines starting +# with '#' will be ignored, and an empty message aborts the commit. +# +# On branch main +# Your branch is ahead of 'origin/main' by 1 commit. +# (use "git push" to publish your local commits) +# +# Changes to be committed: +# modified: OVMF_VARS-pure-efi.fd +# diff --git a/OVMFbin/git folder/FETCH_HEAD b/OVMFbin/git folder/FETCH_HEAD new file mode 100644 index 0000000..8866ddc --- /dev/null +++ b/OVMFbin/git folder/FETCH_HEAD @@ -0,0 +1 @@ +961da169a309a0da546e75e6815df5958ed233e0 branch 'main' of https://github.com/SpookyDervish/OVMFbin diff --git a/OVMFbin/git folder/HEAD b/OVMFbin/git folder/HEAD new file mode 100644 index 0000000..b870d82 --- /dev/null +++ b/OVMFbin/git folder/HEAD @@ -0,0 +1 @@ +ref: refs/heads/main diff --git a/OVMFbin/git folder/ORIG_HEAD b/OVMFbin/git folder/ORIG_HEAD new file mode 100644 index 0000000..417f33f --- /dev/null +++ b/OVMFbin/git folder/ORIG_HEAD @@ -0,0 +1 @@ +961da169a309a0da546e75e6815df5958ed233e0 diff --git a/OVMFbin/git folder/config b/OVMFbin/git folder/config new file mode 100644 index 0000000..a8c18a3 --- /dev/null +++ b/OVMFbin/git folder/config @@ -0,0 +1,15 @@ +[core] + repositoryformatversion = 0 + filemode = true + bare = false + logallrefupdates = true +[remote "upstream"] + url = https://github.com/Absurdponcho/OVMFbin + fetch = +refs/heads/*:refs/remotes/upstream/* +[branch "main"] + remote = origin + vscode-merge-base = origin/main + merge = refs/heads/main +[remote "origin"] + url = https://github.com/SpookyDervish/OVMFbin.git + fetch = +refs/heads/*:refs/remotes/origin/* diff --git a/OVMFbin/git folder/description b/OVMFbin/git folder/description new file mode 100644 index 0000000..498b267 --- /dev/null +++ b/OVMFbin/git folder/description @@ -0,0 +1 @@ +Unnamed repository; edit this file 'description' to name the repository. diff --git a/OVMFbin/git folder/hooks/applypatch-msg.sample b/OVMFbin/git folder/hooks/applypatch-msg.sample new file mode 100755 index 0000000..a5d7b84 --- /dev/null +++ b/OVMFbin/git folder/hooks/applypatch-msg.sample @@ -0,0 +1,15 @@ +#!/bin/sh +# +# An example hook script to check the commit log message taken by +# applypatch from an e-mail message. +# +# The hook should exit with non-zero status after issuing an +# appropriate message if it wants to stop the commit. The hook is +# allowed to edit the commit message file. +# +# To enable this hook, rename this file to "applypatch-msg". + +. git-sh-setup +commitmsg="$(git rev-parse --git-path hooks/commit-msg)" +test -x "$commitmsg" && exec "$commitmsg" ${1+"$@"} +: diff --git a/OVMFbin/git folder/hooks/commit-msg.sample b/OVMFbin/git folder/hooks/commit-msg.sample new file mode 100755 index 0000000..b58d118 --- /dev/null +++ b/OVMFbin/git folder/hooks/commit-msg.sample @@ -0,0 +1,24 @@ +#!/bin/sh +# +# An example hook script to check the commit log message. +# Called by "git commit" with one argument, the name of the file +# that has the commit message. The hook should exit with non-zero +# status after issuing an appropriate message if it wants to stop the +# commit. The hook is allowed to edit the commit message file. +# +# To enable this hook, rename this file to "commit-msg". + +# Uncomment the below to add a Signed-off-by line to the message. +# Doing this in a hook is a bad idea in general, but the prepare-commit-msg +# hook is more suited to it. +# +# SOB=$(git var GIT_AUTHOR_IDENT | sed -n 's/^\(.*>\).*$/Signed-off-by: \1/p') +# grep -qs "^$SOB" "$1" || echo "$SOB" >> "$1" + +# This example catches duplicate Signed-off-by lines. + +test "" = "$(grep '^Signed-off-by: ' "$1" | + sort | uniq -c | sed -e '/^[ ]*1[ ]/d')" || { + echo >&2 Duplicate Signed-off-by lines. + exit 1 +} diff --git a/OVMFbin/git folder/hooks/fsmonitor-watchman.sample b/OVMFbin/git folder/hooks/fsmonitor-watchman.sample new file mode 100755 index 0000000..23e856f --- /dev/null +++ b/OVMFbin/git folder/hooks/fsmonitor-watchman.sample @@ -0,0 +1,174 @@ +#!/usr/bin/perl + +use strict; +use warnings; +use IPC::Open2; + +# An example hook script to integrate Watchman +# (https://facebook.github.io/watchman/) with git to speed up detecting +# new and modified files. +# +# The hook is passed a version (currently 2) and last update token +# formatted as a string and outputs to stdout a new update token and +# all files that have been modified since the update token. Paths must +# be relative to the root of the working tree and separated by a single NUL. +# +# To enable this hook, rename this file to "query-watchman" and set +# 'git config core.fsmonitor .git/hooks/query-watchman' +# +my ($version, $last_update_token) = @ARGV; + +# Uncomment for debugging +# print STDERR "$0 $version $last_update_token\n"; + +# Check the hook interface version +if ($version ne 2) { + die "Unsupported query-fsmonitor hook version '$version'.\n" . + "Falling back to scanning...\n"; +} + +my $git_work_tree = get_working_dir(); + +my $retry = 1; + +my $json_pkg; +eval { + require JSON::XS; + $json_pkg = "JSON::XS"; + 1; +} or do { + require JSON::PP; + $json_pkg = "JSON::PP"; +}; + +launch_watchman(); + +sub launch_watchman { + my $o = watchman_query(); + if (is_work_tree_watched($o)) { + output_result($o->{clock}, @{$o->{files}}); + } +} + +sub output_result { + my ($clockid, @files) = @_; + + # Uncomment for debugging watchman output + # open (my $fh, ">", ".git/watchman-output.out"); + # binmode $fh, ":utf8"; + # print $fh "$clockid\n@files\n"; + # close $fh; + + binmode STDOUT, ":utf8"; + print $clockid; + print "\0"; + local $, = "\0"; + print @files; +} + +sub watchman_clock { + my $response = qx/watchman clock "$git_work_tree"/; + die "Failed to get clock id on '$git_work_tree'.\n" . + "Falling back to scanning...\n" if $? != 0; + + return $json_pkg->new->utf8->decode($response); +} + +sub watchman_query { + my $pid = open2(\*CHLD_OUT, \*CHLD_IN, 'watchman -j --no-pretty') + or die "open2() failed: $!\n" . + "Falling back to scanning...\n"; + + # In the query expression below we're asking for names of files that + # changed since $last_update_token but not from the .git folder. + # + # To accomplish this, we're using the "since" generator to use the + # recency index to select candidate nodes and "fields" to limit the + # output to file names only. Then we're using the "expression" term to + # further constrain the results. + my $last_update_line = ""; + if (substr($last_update_token, 0, 1) eq "c") { + $last_update_token = "\"$last_update_token\""; + $last_update_line = qq[\n"since": $last_update_token,]; + } + my $query = <<" END"; + ["query", "$git_work_tree", {$last_update_line + "fields": ["name"], + "expression": ["not", ["dirname", ".git"]] + }] + END + + # Uncomment for debugging the watchman query + # open (my $fh, ">", ".git/watchman-query.json"); + # print $fh $query; + # close $fh; + + print CHLD_IN $query; + close CHLD_IN; + my $response = do {local $/; }; + + # Uncomment for debugging the watch response + # open ($fh, ">", ".git/watchman-response.json"); + # print $fh $response; + # close $fh; + + die "Watchman: command returned no output.\n" . + "Falling back to scanning...\n" if $response eq ""; + die "Watchman: command returned invalid output: $response\n" . + "Falling back to scanning...\n" unless $response =~ /^\{/; + + return $json_pkg->new->utf8->decode($response); +} + +sub is_work_tree_watched { + my ($output) = @_; + my $error = $output->{error}; + if ($retry > 0 and $error and $error =~ m/unable to resolve root .* directory (.*) is not watched/) { + $retry--; + my $response = qx/watchman watch "$git_work_tree"/; + die "Failed to make watchman watch '$git_work_tree'.\n" . + "Falling back to scanning...\n" if $? != 0; + $output = $json_pkg->new->utf8->decode($response); + $error = $output->{error}; + die "Watchman: $error.\n" . + "Falling back to scanning...\n" if $error; + + # Uncomment for debugging watchman output + # open (my $fh, ">", ".git/watchman-output.out"); + # close $fh; + + # Watchman will always return all files on the first query so + # return the fast "everything is dirty" flag to git and do the + # Watchman query just to get it over with now so we won't pay + # the cost in git to look up each individual file. + my $o = watchman_clock(); + $error = $output->{error}; + + die "Watchman: $error.\n" . + "Falling back to scanning...\n" if $error; + + output_result($o->{clock}, ("/")); + $last_update_token = $o->{clock}; + + eval { launch_watchman() }; + return 0; + } + + die "Watchman: $error.\n" . + "Falling back to scanning...\n" if $error; + + return 1; +} + +sub get_working_dir { + my $working_dir; + if ($^O =~ 'msys' || $^O =~ 'cygwin') { + $working_dir = Win32::GetCwd(); + $working_dir =~ tr/\\/\//; + } else { + require Cwd; + $working_dir = Cwd::cwd(); + } + + return $working_dir; +} diff --git a/OVMFbin/git folder/hooks/post-update.sample b/OVMFbin/git folder/hooks/post-update.sample new file mode 100755 index 0000000..ec17ec1 --- /dev/null +++ b/OVMFbin/git folder/hooks/post-update.sample @@ -0,0 +1,8 @@ +#!/bin/sh +# +# An example hook script to prepare a packed repository for use over +# dumb transports. +# +# To enable this hook, rename this file to "post-update". + +exec git update-server-info diff --git a/OVMFbin/git folder/hooks/pre-applypatch.sample b/OVMFbin/git folder/hooks/pre-applypatch.sample new file mode 100755 index 0000000..4142082 --- /dev/null +++ b/OVMFbin/git folder/hooks/pre-applypatch.sample @@ -0,0 +1,14 @@ +#!/bin/sh +# +# An example hook script to verify what is about to be committed +# by applypatch from an e-mail message. +# +# The hook should exit with non-zero status after issuing an +# appropriate message if it wants to stop the commit. +# +# To enable this hook, rename this file to "pre-applypatch". + +. git-sh-setup +precommit="$(git rev-parse --git-path hooks/pre-commit)" +test -x "$precommit" && exec "$precommit" ${1+"$@"} +: diff --git a/OVMFbin/git folder/hooks/pre-commit.sample b/OVMFbin/git folder/hooks/pre-commit.sample new file mode 100755 index 0000000..29ed5ee --- /dev/null +++ b/OVMFbin/git folder/hooks/pre-commit.sample @@ -0,0 +1,49 @@ +#!/bin/sh +# +# An example hook script to verify what is about to be committed. +# Called by "git commit" with no arguments. The hook should +# exit with non-zero status after issuing an appropriate message if +# it wants to stop the commit. +# +# To enable this hook, rename this file to "pre-commit". + +if git rev-parse --verify HEAD >/dev/null 2>&1 +then + against=HEAD +else + # Initial commit: diff against an empty tree object + against=$(git hash-object -t tree /dev/null) +fi + +# If you want to allow non-ASCII filenames set this variable to true. +allownonascii=$(git config --type=bool hooks.allownonascii) + +# Redirect output to stderr. +exec 1>&2 + +# Cross platform projects tend to avoid non-ASCII filenames; prevent +# them from being added to the repository. We exploit the fact that the +# printable range starts at the space character and ends with tilde. +if [ "$allownonascii" != "true" ] && + # Note that the use of brackets around a tr range is ok here, (it's + # even required, for portability to Solaris 10's /usr/bin/tr), since + # the square bracket bytes happen to fall in the designated range. + test $(git diff-index --cached --name-only --diff-filter=A -z $against | + LC_ALL=C tr -d '[ -~]\0' | wc -c) != 0 +then + cat <<\EOF +Error: Attempt to add a non-ASCII file name. + +This can cause problems if you want to work with people on other platforms. + +To be portable it is advisable to rename the file. + +If you know what you are doing you can disable this check using: + + git config hooks.allownonascii true +EOF + exit 1 +fi + +# If there are whitespace errors, print the offending file names and fail. +exec git diff-index --check --cached $against -- diff --git a/OVMFbin/git folder/hooks/pre-merge-commit.sample b/OVMFbin/git folder/hooks/pre-merge-commit.sample new file mode 100755 index 0000000..399eab1 --- /dev/null +++ b/OVMFbin/git folder/hooks/pre-merge-commit.sample @@ -0,0 +1,13 @@ +#!/bin/sh +# +# An example hook script to verify what is about to be committed. +# Called by "git merge" with no arguments. The hook should +# exit with non-zero status after issuing an appropriate message to +# stderr if it wants to stop the merge commit. +# +# To enable this hook, rename this file to "pre-merge-commit". + +. git-sh-setup +test -x "$GIT_DIR/hooks/pre-commit" && + exec "$GIT_DIR/hooks/pre-commit" +: diff --git a/OVMFbin/git folder/hooks/pre-push.sample b/OVMFbin/git folder/hooks/pre-push.sample new file mode 100755 index 0000000..4ce688d --- /dev/null +++ b/OVMFbin/git folder/hooks/pre-push.sample @@ -0,0 +1,53 @@ +#!/bin/sh + +# An example hook script to verify what is about to be pushed. Called by "git +# push" after it has checked the remote status, but before anything has been +# pushed. If this script exits with a non-zero status nothing will be pushed. +# +# This hook is called with the following parameters: +# +# $1 -- Name of the remote to which the push is being done +# $2 -- URL to which the push is being done +# +# If pushing without using a named remote those arguments will be equal. +# +# Information about the commits which are being pushed is supplied as lines to +# the standard input in the form: +# +# +# +# This sample shows how to prevent push of commits where the log message starts +# with "WIP" (work in progress). + +remote="$1" +url="$2" + +zero=$(git hash-object --stdin &2 "Found WIP commit in $local_ref, not pushing" + exit 1 + fi + fi +done + +exit 0 diff --git a/OVMFbin/git folder/hooks/pre-rebase.sample b/OVMFbin/git folder/hooks/pre-rebase.sample new file mode 100755 index 0000000..6cbef5c --- /dev/null +++ b/OVMFbin/git folder/hooks/pre-rebase.sample @@ -0,0 +1,169 @@ +#!/bin/sh +# +# Copyright (c) 2006, 2008 Junio C Hamano +# +# The "pre-rebase" hook is run just before "git rebase" starts doing +# its job, and can prevent the command from running by exiting with +# non-zero status. +# +# The hook is called with the following parameters: +# +# $1 -- the upstream the series was forked from. +# $2 -- the branch being rebased (or empty when rebasing the current branch). +# +# This sample shows how to prevent topic branches that are already +# merged to 'next' branch from getting rebased, because allowing it +# would result in rebasing already published history. + +publish=next +basebranch="$1" +if test "$#" = 2 +then + topic="refs/heads/$2" +else + topic=`git symbolic-ref HEAD` || + exit 0 ;# we do not interrupt rebasing detached HEAD +fi + +case "$topic" in +refs/heads/??/*) + ;; +*) + exit 0 ;# we do not interrupt others. + ;; +esac + +# Now we are dealing with a topic branch being rebased +# on top of master. Is it OK to rebase it? + +# Does the topic really exist? +git show-ref -q "$topic" || { + echo >&2 "No such branch $topic" + exit 1 +} + +# Is topic fully merged to master? +not_in_master=`git rev-list --pretty=oneline ^master "$topic"` +if test -z "$not_in_master" +then + echo >&2 "$topic is fully merged to master; better remove it." + exit 1 ;# we could allow it, but there is no point. +fi + +# Is topic ever merged to next? If so you should not be rebasing it. +only_next_1=`git rev-list ^master "^$topic" ${publish} | sort` +only_next_2=`git rev-list ^master ${publish} | sort` +if test "$only_next_1" = "$only_next_2" +then + not_in_topic=`git rev-list "^$topic" master` + if test -z "$not_in_topic" + then + echo >&2 "$topic is already up to date with master" + exit 1 ;# we could allow it, but there is no point. + else + exit 0 + fi +else + not_in_next=`git rev-list --pretty=oneline ^${publish} "$topic"` + /usr/bin/perl -e ' + my $topic = $ARGV[0]; + my $msg = "* $topic has commits already merged to public branch:\n"; + my (%not_in_next) = map { + /^([0-9a-f]+) /; + ($1 => 1); + } split(/\n/, $ARGV[1]); + for my $elem (map { + /^([0-9a-f]+) (.*)$/; + [$1 => $2]; + } split(/\n/, $ARGV[2])) { + if (!exists $not_in_next{$elem->[0]}) { + if ($msg) { + print STDERR $msg; + undef $msg; + } + print STDERR " $elem->[1]\n"; + } + } + ' "$topic" "$not_in_next" "$not_in_master" + exit 1 +fi + +<<\DOC_END + +This sample hook safeguards topic branches that have been +published from being rewound. + +The workflow assumed here is: + + * Once a topic branch forks from "master", "master" is never + merged into it again (either directly or indirectly). + + * Once a topic branch is fully cooked and merged into "master", + it is deleted. If you need to build on top of it to correct + earlier mistakes, a new topic branch is created by forking at + the tip of the "master". This is not strictly necessary, but + it makes it easier to keep your history simple. + + * Whenever you need to test or publish your changes to topic + branches, merge them into "next" branch. + +The script, being an example, hardcodes the publish branch name +to be "next", but it is trivial to make it configurable via +$GIT_DIR/config mechanism. + +With this workflow, you would want to know: + +(1) ... if a topic branch has ever been merged to "next". Young + topic branches can have stupid mistakes you would rather + clean up before publishing, and things that have not been + merged into other branches can be easily rebased without + affecting other people. But once it is published, you would + not want to rewind it. + +(2) ... if a topic branch has been fully merged to "master". + Then you can delete it. More importantly, you should not + build on top of it -- other people may already want to + change things related to the topic as patches against your + "master", so if you need further changes, it is better to + fork the topic (perhaps with the same name) afresh from the + tip of "master". + +Let's look at this example: + + o---o---o---o---o---o---o---o---o---o "next" + / / / / + / a---a---b A / / + / / / / + / / c---c---c---c B / + / / / \ / + / / / b---b C \ / + / / / / \ / + ---o---o---o---o---o---o---o---o---o---o---o "master" + + +A, B and C are topic branches. + + * A has one fix since it was merged up to "next". + + * B has finished. It has been fully merged up to "master" and "next", + and is ready to be deleted. + + * C has not merged to "next" at all. + +We would want to allow C to be rebased, refuse A, and encourage +B to be deleted. + +To compute (1): + + git rev-list ^master ^topic next + git rev-list ^master next + + if these match, topic has not merged in next at all. + +To compute (2): + + git rev-list master..topic + + if this is empty, it is fully merged to "master". + +DOC_END diff --git a/OVMFbin/git folder/hooks/pre-receive.sample b/OVMFbin/git folder/hooks/pre-receive.sample new file mode 100755 index 0000000..a1fd29e --- /dev/null +++ b/OVMFbin/git folder/hooks/pre-receive.sample @@ -0,0 +1,24 @@ +#!/bin/sh +# +# An example hook script to make use of push options. +# The example simply echoes all push options that start with 'echoback=' +# and rejects all pushes when the "reject" push option is used. +# +# To enable this hook, rename this file to "pre-receive". + +if test -n "$GIT_PUSH_OPTION_COUNT" +then + i=0 + while test "$i" -lt "$GIT_PUSH_OPTION_COUNT" + do + eval "value=\$GIT_PUSH_OPTION_$i" + case "$value" in + echoback=*) + echo "echo from the pre-receive-hook: ${value#*=}" >&2 + ;; + reject) + exit 1 + esac + i=$((i + 1)) + done +fi diff --git a/OVMFbin/git folder/hooks/prepare-commit-msg.sample b/OVMFbin/git folder/hooks/prepare-commit-msg.sample new file mode 100755 index 0000000..10fa14c --- /dev/null +++ b/OVMFbin/git folder/hooks/prepare-commit-msg.sample @@ -0,0 +1,42 @@ +#!/bin/sh +# +# An example hook script to prepare the commit log message. +# Called by "git commit" with the name of the file that has the +# commit message, followed by the description of the commit +# message's source. The hook's purpose is to edit the commit +# message file. If the hook fails with a non-zero status, +# the commit is aborted. +# +# To enable this hook, rename this file to "prepare-commit-msg". + +# This hook includes three examples. The first one removes the +# "# Please enter the commit message..." help message. +# +# The second includes the output of "git diff --name-status -r" +# into the message, just before the "git status" output. It is +# commented because it doesn't cope with --amend or with squashed +# commits. +# +# The third example adds a Signed-off-by line to the message, that can +# still be edited. This is rarely a good idea. + +COMMIT_MSG_FILE=$1 +COMMIT_SOURCE=$2 +SHA1=$3 + +/usr/bin/perl -i.bak -ne 'print unless(m/^. Please enter the commit message/..m/^#$/)' "$COMMIT_MSG_FILE" + +# case "$COMMIT_SOURCE,$SHA1" in +# ,|template,) +# /usr/bin/perl -i.bak -pe ' +# print "\n" . `git diff --cached --name-status -r` +# if /^#/ && $first++ == 0' "$COMMIT_MSG_FILE" ;; +# *) ;; +# esac + +# SOB=$(git var GIT_COMMITTER_IDENT | sed -n 's/^\(.*>\).*$/Signed-off-by: \1/p') +# git interpret-trailers --in-place --trailer "$SOB" "$COMMIT_MSG_FILE" +# if test -z "$COMMIT_SOURCE" +# then +# /usr/bin/perl -i.bak -pe 'print "\n" if !$first_line++' "$COMMIT_MSG_FILE" +# fi diff --git a/OVMFbin/git folder/hooks/push-to-checkout.sample b/OVMFbin/git folder/hooks/push-to-checkout.sample new file mode 100755 index 0000000..af5a0c0 --- /dev/null +++ b/OVMFbin/git folder/hooks/push-to-checkout.sample @@ -0,0 +1,78 @@ +#!/bin/sh + +# An example hook script to update a checked-out tree on a git push. +# +# This hook is invoked by git-receive-pack(1) when it reacts to git +# push and updates reference(s) in its repository, and when the push +# tries to update the branch that is currently checked out and the +# receive.denyCurrentBranch configuration variable is set to +# updateInstead. +# +# By default, such a push is refused if the working tree and the index +# of the remote repository has any difference from the currently +# checked out commit; when both the working tree and the index match +# the current commit, they are updated to match the newly pushed tip +# of the branch. This hook is to be used to override the default +# behaviour; however the code below reimplements the default behaviour +# as a starting point for convenient modification. +# +# The hook receives the commit with which the tip of the current +# branch is going to be updated: +commit=$1 + +# It can exit with a non-zero status to refuse the push (when it does +# so, it must not modify the index or the working tree). +die () { + echo >&2 "$*" + exit 1 +} + +# Or it can make any necessary changes to the working tree and to the +# index to bring them to the desired state when the tip of the current +# branch is updated to the new commit, and exit with a zero status. +# +# For example, the hook can simply run git read-tree -u -m HEAD "$1" +# in order to emulate git fetch that is run in the reverse direction +# with git push, as the two-tree form of git read-tree -u -m is +# essentially the same as git switch or git checkout that switches +# branches while keeping the local changes in the working tree that do +# not interfere with the difference between the branches. + +# The below is a more-or-less exact translation to shell of the C code +# for the default behaviour for git's push-to-checkout hook defined in +# the push_to_deploy() function in builtin/receive-pack.c. +# +# Note that the hook will be executed from the repository directory, +# not from the working tree, so if you want to perform operations on +# the working tree, you will have to adapt your code accordingly, e.g. +# by adding "cd .." or using relative paths. + +if ! git update-index -q --ignore-submodules --refresh +then + die "Up-to-date check failed" +fi + +if ! git diff-files --quiet --ignore-submodules -- +then + die "Working directory has unstaged changes" +fi + +# This is a rough translation of: +# +# head_has_history() ? "HEAD" : EMPTY_TREE_SHA1_HEX +if git cat-file -e HEAD 2>/dev/null +then + head=HEAD +else + head=$(git hash-object -t tree --stdin &2 + exit 1 +} + +unset GIT_DIR GIT_WORK_TREE +cd "$worktree" && + +if grep -q "^diff --git " "$1" +then + validate_patch "$1" +else + validate_cover_letter "$1" +fi && + +if test "$GIT_SENDEMAIL_FILE_COUNTER" = "$GIT_SENDEMAIL_FILE_TOTAL" +then + git config --unset-all sendemail.validateWorktree && + trap 'git worktree remove -ff "$worktree"' EXIT && + validate_series +fi diff --git a/OVMFbin/git folder/hooks/update.sample b/OVMFbin/git folder/hooks/update.sample new file mode 100755 index 0000000..c4d426b --- /dev/null +++ b/OVMFbin/git folder/hooks/update.sample @@ -0,0 +1,128 @@ +#!/bin/sh +# +# An example hook script to block unannotated tags from entering. +# Called by "git receive-pack" with arguments: refname sha1-old sha1-new +# +# To enable this hook, rename this file to "update". +# +# Config +# ------ +# hooks.allowunannotated +# This boolean sets whether unannotated tags will be allowed into the +# repository. By default they won't be. +# hooks.allowdeletetag +# This boolean sets whether deleting tags will be allowed in the +# repository. By default they won't be. +# hooks.allowmodifytag +# This boolean sets whether a tag may be modified after creation. By default +# it won't be. +# hooks.allowdeletebranch +# This boolean sets whether deleting branches will be allowed in the +# repository. By default they won't be. +# hooks.denycreatebranch +# This boolean sets whether remotely creating branches will be denied +# in the repository. By default this is allowed. +# + +# --- Command line +refname="$1" +oldrev="$2" +newrev="$3" + +# --- Safety check +if [ -z "$GIT_DIR" ]; then + echo "Don't run this script from the command line." >&2 + echo " (if you want, you could supply GIT_DIR then run" >&2 + echo " $0 )" >&2 + exit 1 +fi + +if [ -z "$refname" -o -z "$oldrev" -o -z "$newrev" ]; then + echo "usage: $0 " >&2 + exit 1 +fi + +# --- Config +allowunannotated=$(git config --type=bool hooks.allowunannotated) +allowdeletebranch=$(git config --type=bool hooks.allowdeletebranch) +denycreatebranch=$(git config --type=bool hooks.denycreatebranch) +allowdeletetag=$(git config --type=bool hooks.allowdeletetag) +allowmodifytag=$(git config --type=bool hooks.allowmodifytag) + +# check for no description +projectdesc=$(sed -e '1q' "$GIT_DIR/description") +case "$projectdesc" in +"Unnamed repository"* | "") + echo "*** Project description file hasn't been set" >&2 + exit 1 + ;; +esac + +# --- Check types +# if $newrev is 0000...0000, it's a commit to delete a ref. +zero=$(git hash-object --stdin &2 + echo "*** Use 'git tag [ -a | -s ]' for tags you want to propagate." >&2 + exit 1 + fi + ;; + refs/tags/*,delete) + # delete tag + if [ "$allowdeletetag" != "true" ]; then + echo "*** Deleting a tag is not allowed in this repository" >&2 + exit 1 + fi + ;; + refs/tags/*,tag) + # annotated tag + if [ "$allowmodifytag" != "true" ] && git rev-parse $refname > /dev/null 2>&1 + then + echo "*** Tag '$refname' already exists." >&2 + echo "*** Modifying a tag is not allowed in this repository." >&2 + exit 1 + fi + ;; + refs/heads/*,commit) + # branch + if [ "$oldrev" = "$zero" -a "$denycreatebranch" = "true" ]; then + echo "*** Creating a branch is not allowed in this repository" >&2 + exit 1 + fi + ;; + refs/heads/*,delete) + # delete branch + if [ "$allowdeletebranch" != "true" ]; then + echo "*** Deleting a branch is not allowed in this repository" >&2 + exit 1 + fi + ;; + refs/remotes/*,commit) + # tracking branch + ;; + refs/remotes/*,delete) + # delete tracking branch + if [ "$allowdeletebranch" != "true" ]; then + echo "*** Deleting a tracking branch is not allowed in this repository" >&2 + exit 1 + fi + ;; + *) + # Anything else (is there anything else?) + echo "*** Update hook: unknown type of update to ref $refname of type $newrev_type" >&2 + exit 1 + ;; +esac + +# --- Finished +exit 0 diff --git a/OVMFbin/git folder/index b/OVMFbin/git folder/index new file mode 100644 index 0000000..d75bf20 Binary files /dev/null and b/OVMFbin/git folder/index differ diff --git a/OVMFbin/git folder/info/exclude b/OVMFbin/git folder/info/exclude new file mode 100644 index 0000000..a5196d1 --- /dev/null +++ b/OVMFbin/git folder/info/exclude @@ -0,0 +1,6 @@ +# git ls-files --others --exclude-from=.git/info/exclude +# Lines that start with '#' are comments. +# For a project mostly in C, the following would be a good set of +# exclude patterns (uncomment them if you want to use them): +# *.[oa] +# *~ diff --git a/OVMFbin/git folder/logs/HEAD b/OVMFbin/git folder/logs/HEAD new file mode 100644 index 0000000..3b1f28a --- /dev/null +++ b/OVMFbin/git folder/logs/HEAD @@ -0,0 +1,3 @@ +0000000000000000000000000000000000000000 6785366a291c513f51595e631c52e9ec176a2d74 SpookyDervish 1769496465 +1100 clone: from https://github.com/Absurdponcho/OVMFbin +6785366a291c513f51595e631c52e9ec176a2d74 80038c0fa6a4195ef4d08ae695913651bd440ea7 SpookyDervish 1769498258 +1100 commit: build +80038c0fa6a4195ef4d08ae695913651bd440ea7 961da169a309a0da546e75e6815df5958ed233e0 SpookyDervish 1769503659 +1100 commit: load kernel with bootloader diff --git a/OVMFbin/git folder/logs/refs/heads/main b/OVMFbin/git folder/logs/refs/heads/main new file mode 100644 index 0000000..3b1f28a --- /dev/null +++ b/OVMFbin/git folder/logs/refs/heads/main @@ -0,0 +1,3 @@ +0000000000000000000000000000000000000000 6785366a291c513f51595e631c52e9ec176a2d74 SpookyDervish 1769496465 +1100 clone: from https://github.com/Absurdponcho/OVMFbin +6785366a291c513f51595e631c52e9ec176a2d74 80038c0fa6a4195ef4d08ae695913651bd440ea7 SpookyDervish 1769498258 +1100 commit: build +80038c0fa6a4195ef4d08ae695913651bd440ea7 961da169a309a0da546e75e6815df5958ed233e0 SpookyDervish 1769503659 +1100 commit: load kernel with bootloader diff --git a/OVMFbin/git folder/logs/refs/remotes/origin/HEAD b/OVMFbin/git folder/logs/refs/remotes/origin/HEAD new file mode 100644 index 0000000..f46e87f --- /dev/null +++ b/OVMFbin/git folder/logs/refs/remotes/origin/HEAD @@ -0,0 +1 @@ +0000000000000000000000000000000000000000 961da169a309a0da546e75e6815df5958ed233e0 SpookyDervish 1769503875 +1100 fetch diff --git a/OVMFbin/git folder/logs/refs/remotes/origin/main b/OVMFbin/git folder/logs/refs/remotes/origin/main new file mode 100644 index 0000000..20cfc77 --- /dev/null +++ b/OVMFbin/git folder/logs/refs/remotes/origin/main @@ -0,0 +1,2 @@ +0000000000000000000000000000000000000000 6785366a291c513f51595e631c52e9ec176a2d74 SpookyDervish 1769503681 +1100 fetch origin main: storing head +6785366a291c513f51595e631c52e9ec176a2d74 961da169a309a0da546e75e6815df5958ed233e0 SpookyDervish 1769503682 +1100 update by push diff --git a/OVMFbin/git folder/logs/refs/remotes/upstream/HEAD b/OVMFbin/git folder/logs/refs/remotes/upstream/HEAD new file mode 100644 index 0000000..56428a4 --- /dev/null +++ b/OVMFbin/git folder/logs/refs/remotes/upstream/HEAD @@ -0,0 +1,2 @@ +0000000000000000000000000000000000000000 6785366a291c513f51595e631c52e9ec176a2d74 SpookyDervish 1769496465 +1100 clone: from https://github.com/Absurdponcho/OVMFbin +0000000000000000000000000000000000000000 0000000000000000000000000000000000000000 Nathaniel 1769503680 +1100 remote: renamed refs/remotes/origin/HEAD to refs/remotes/upstream/HEAD diff --git a/OVMFbin/git folder/objects/01/b10f8b34765b71eb9eddc0097bc14619a7e945 b/OVMFbin/git folder/objects/01/b10f8b34765b71eb9eddc0097bc14619a7e945 new file mode 100644 index 0000000..e440372 Binary files /dev/null and b/OVMFbin/git folder/objects/01/b10f8b34765b71eb9eddc0097bc14619a7e945 differ diff --git a/OVMFbin/git folder/objects/07/1ebe00d165cfa2d86c19acefa051b611476453 b/OVMFbin/git folder/objects/07/1ebe00d165cfa2d86c19acefa051b611476453 new file mode 100644 index 0000000..b131563 Binary files /dev/null and b/OVMFbin/git folder/objects/07/1ebe00d165cfa2d86c19acefa051b611476453 differ diff --git a/OVMFbin/git folder/objects/1c/7572aeab4405be13c8702442158cede75edb16 b/OVMFbin/git folder/objects/1c/7572aeab4405be13c8702442158cede75edb16 new file mode 100644 index 0000000..7061626 Binary files /dev/null and b/OVMFbin/git folder/objects/1c/7572aeab4405be13c8702442158cede75edb16 differ diff --git a/OVMFbin/git folder/objects/21/a20a241fffaa41a7020e608eae83c34305c88d b/OVMFbin/git folder/objects/21/a20a241fffaa41a7020e608eae83c34305c88d new file mode 100644 index 0000000..2a4d192 Binary files /dev/null and b/OVMFbin/git folder/objects/21/a20a241fffaa41a7020e608eae83c34305c88d differ diff --git a/OVMFbin/git folder/objects/26/645be2a0c6d6e1ad86f8dda96142b9dfd1fe4b b/OVMFbin/git folder/objects/26/645be2a0c6d6e1ad86f8dda96142b9dfd1fe4b new file mode 100644 index 0000000..59f4733 Binary files /dev/null and b/OVMFbin/git folder/objects/26/645be2a0c6d6e1ad86f8dda96142b9dfd1fe4b differ diff --git a/OVMFbin/git folder/objects/34/7d047ac92878bd6309f2a3cff3e1bc71f2484e b/OVMFbin/git folder/objects/34/7d047ac92878bd6309f2a3cff3e1bc71f2484e new file mode 100644 index 0000000..2720941 Binary files /dev/null and b/OVMFbin/git folder/objects/34/7d047ac92878bd6309f2a3cff3e1bc71f2484e differ diff --git a/OVMFbin/git folder/objects/35/272d37babdc5b39f119734ae319e7d6d4b0f3c b/OVMFbin/git folder/objects/35/272d37babdc5b39f119734ae319e7d6d4b0f3c new file mode 100644 index 0000000..8a7e2d0 Binary files /dev/null and b/OVMFbin/git folder/objects/35/272d37babdc5b39f119734ae319e7d6d4b0f3c differ diff --git a/OVMFbin/git folder/objects/3b/8bb9b61b0278fa5ac258b1a5b4460d1f681d16 b/OVMFbin/git folder/objects/3b/8bb9b61b0278fa5ac258b1a5b4460d1f681d16 new file mode 100644 index 0000000..4ab71f5 Binary files /dev/null and b/OVMFbin/git folder/objects/3b/8bb9b61b0278fa5ac258b1a5b4460d1f681d16 differ diff --git a/OVMFbin/git folder/objects/40/0e200d5c4ce780b1adc8862a6e984d38f4c661 b/OVMFbin/git folder/objects/40/0e200d5c4ce780b1adc8862a6e984d38f4c661 new file mode 100644 index 0000000..b2db1f6 Binary files /dev/null and b/OVMFbin/git folder/objects/40/0e200d5c4ce780b1adc8862a6e984d38f4c661 differ diff --git a/OVMFbin/git folder/objects/43/62fbf6b936c8b381348dde16151e224dec131f b/OVMFbin/git folder/objects/43/62fbf6b936c8b381348dde16151e224dec131f new file mode 100644 index 0000000..805cbb1 Binary files /dev/null and b/OVMFbin/git folder/objects/43/62fbf6b936c8b381348dde16151e224dec131f differ diff --git a/OVMFbin/git folder/objects/44/948262475f2d9992b2682e0ba2dccef9c8e4f8 b/OVMFbin/git folder/objects/44/948262475f2d9992b2682e0ba2dccef9c8e4f8 new file mode 100644 index 0000000..ad86971 Binary files /dev/null and b/OVMFbin/git folder/objects/44/948262475f2d9992b2682e0ba2dccef9c8e4f8 differ diff --git a/OVMFbin/git folder/objects/4c/a792b3ea67029a92cb97658697faef535d9f0b b/OVMFbin/git folder/objects/4c/a792b3ea67029a92cb97658697faef535d9f0b new file mode 100644 index 0000000..b90a622 Binary files /dev/null and b/OVMFbin/git folder/objects/4c/a792b3ea67029a92cb97658697faef535d9f0b differ diff --git a/OVMFbin/git folder/objects/5c/57dcfddccc3df31127d67f3a8a01d3b83200f9 b/OVMFbin/git folder/objects/5c/57dcfddccc3df31127d67f3a8a01d3b83200f9 new file mode 100644 index 0000000..38a7827 Binary files /dev/null and b/OVMFbin/git folder/objects/5c/57dcfddccc3df31127d67f3a8a01d3b83200f9 differ diff --git a/OVMFbin/git folder/objects/67/85366a291c513f51595e631c52e9ec176a2d74 b/OVMFbin/git folder/objects/67/85366a291c513f51595e631c52e9ec176a2d74 new file mode 100644 index 0000000..bd00f5c Binary files /dev/null and b/OVMFbin/git folder/objects/67/85366a291c513f51595e631c52e9ec176a2d74 differ diff --git a/OVMFbin/git folder/objects/74/07bc4cba4b8af3bf2338e5973eda6e0e262549 b/OVMFbin/git folder/objects/74/07bc4cba4b8af3bf2338e5973eda6e0e262549 new file mode 100644 index 0000000..0a01949 Binary files /dev/null and b/OVMFbin/git folder/objects/74/07bc4cba4b8af3bf2338e5973eda6e0e262549 differ diff --git a/OVMFbin/git folder/objects/7f/ea89a46ceeb8929b0dedd6cd432dd89a3c4a5a b/OVMFbin/git folder/objects/7f/ea89a46ceeb8929b0dedd6cd432dd89a3c4a5a new file mode 100644 index 0000000..7e5f15f Binary files /dev/null and b/OVMFbin/git folder/objects/7f/ea89a46ceeb8929b0dedd6cd432dd89a3c4a5a differ diff --git a/OVMFbin/git folder/objects/80/038c0fa6a4195ef4d08ae695913651bd440ea7 b/OVMFbin/git folder/objects/80/038c0fa6a4195ef4d08ae695913651bd440ea7 new file mode 100644 index 0000000..759feee Binary files /dev/null and b/OVMFbin/git folder/objects/80/038c0fa6a4195ef4d08ae695913651bd440ea7 differ diff --git a/OVMFbin/git folder/objects/81/c7636ea7c847685c0c293dbe67d69e1a0e3ea5 b/OVMFbin/git folder/objects/81/c7636ea7c847685c0c293dbe67d69e1a0e3ea5 new file mode 100644 index 0000000..64097af Binary files /dev/null and b/OVMFbin/git folder/objects/81/c7636ea7c847685c0c293dbe67d69e1a0e3ea5 differ diff --git a/OVMFbin/git folder/objects/8a/73c7937a30a1f45a66bdf26738de6fa6e069d7 b/OVMFbin/git folder/objects/8a/73c7937a30a1f45a66bdf26738de6fa6e069d7 new file mode 100644 index 0000000..93b74eb Binary files /dev/null and b/OVMFbin/git folder/objects/8a/73c7937a30a1f45a66bdf26738de6fa6e069d7 differ diff --git a/OVMFbin/git folder/objects/8f/5bad0a8d529e60057822964037c6690d0563bc b/OVMFbin/git folder/objects/8f/5bad0a8d529e60057822964037c6690d0563bc new file mode 100644 index 0000000..de7e52e --- /dev/null +++ b/OVMFbin/git folder/objects/8f/5bad0a8d529e60057822964037c6690d0563bc @@ -0,0 +1,3131 @@ +xKOR04330`@O{zldgv&ֽp@ +$-?* LkR`?5ϊ ?At_yEsD}zn>*nCB? 1͈{'b47N)%b'0[`Ǡcp7fq k6Xl>)jv嚟w54ϥ\u_>󳪩k=ewZn?8sU z/wXbTX\-\WVjl=ڝO# ~-{SWlI[Ѕ,.ɷ>@AHyO\[+} ϶.NұgfR;=e ޛrUi*?d]*:R4M_Zk\;=Z3  +~?`e{{︮#7>I2;f]yWС?ev'a{aqłQBrԶ;>ם4`#x75k\'7rR߸4Ӧ=my[9=T3#!;s7E'K?7~KUGUWncca=®*7^n^lᮞY™ѵ'M9p]blk FΝNRs?MeQ*,hiA&ka2t9p=NLn89L=|Q%/}ClԹE \҆P Ѿc܅,uxc]@O Կtc8[ʓR挀gGw,L_|ElU'V:$PtNJ[&.+|zcrx^RI>_0%=q05ϡIBa:_8x>_vgkYfGXlYmwz]gȣOls]pޅŋKm5K~ws~u;EU9co]"k׋sJů%q̹|q";{Zx~$G- + +|T~vGL!Eo;?,sw,opy_Qb׻w ܰӃP_ \:\^|!Ws6sKb'r3m|l^íp9M>1yb]:%'\.EsƂLs٦q,LoJMƄ*"⓺W8FPǶ1\~˗6$鶺=i{߽]tY?z=<O0_O$ӭ̻Eǿ<͹ML}l +s[?H;4Djəs/q۱)TY_TUE}j8Yn1O883k;TG~=0.@Oߓth+w^^5뜗G,}On&/z_he1w~q5.qO0 (.#^&FIg<ܴ˾Ţϗ'm.U+u'o]g!Ͽ)93ooO؄_=Xi[m+aBԛ ^,&aw6>˯(NtJ?fY5ONXPћ_>Nk{7c,L LHp~j;Y;Y1Y}{& Eʹ1ʇ *%fn;'!n9\Խ$3f75iȧu"{Y+a(|sY sAӛe[=ģg?vӵﲞh%NJ1Q䮚|j8%*r;;?rC+;9q5Lq'-;]d,} —7*ײjO3v-\:{"'/̘6eAֲJ,+_||w0MV$tj7B6=P(weZ-'=8.?|KoNYVs*qB^dOmf̘nGNn6ܙ71WU7F䦵}0|Si k/l{x"zՋ>9rn .6U鵮2򮽡5rAoe([צ6%ϴIh|nm&'`FI.l[3[MtWZk?ۼ]7rvҽ&0ڸ?g{v +'9SZyfk7y6t' 9Ld鬇^ZW-4]>{+gtFd.QmlUVt_D́ +#?;1u}G?yh.OL `> ap d7'mzk:CJmgd8Uijwל5bά f??γ/.-2[u^/ΔT^=-if|,慏\.HRY;cJ;M K?lU8c"ۅbBvU*i7Q6c1V-2O}mwrcif5B^+=\eNzJS W2;a᳑ g-WVN Dv 9Ɨ]_1K F;nds^YۙYN>*:䃷~:vo%wP*sm$@eSW*<_(mm99ѭuatῸ<r!v2_-Yq*I9/>oM)|Ƹ.Mi׺% +vY3x'm;I2Ǭ+:^*"S7 ?ֻ93B>N-IK&"y/i7]*9la8C$Tk{I*aP2T[lk;xΛǺ-W_}㻒]ߥ\҃;efmmgL> h!ЭtߒYAsʵRoٓ"EE3׵z&p* >n;>V̈́.soLp?dO)}+?-\~~{HISZK +;ƽ-x$3`mO 2ny鈴KWtkNT(uRU s&{fBk*vg//8_4V:{ً#V:muĪ%ٔ3Ӗv$"[9ӽ u<^͡OLk[tBs +.i};e kOKaxUmIâ}Wr0Ӛc_?lmw* mq'~)~òg}NrTjm fEDCq +\"_(za)9^OGkko/tS>B\|kµmro;p|zϛw>[kzG?My~hi8SݳL/O]jsYs-[  +So^\#:h Ϙ ئ?eu93yQWQ.juFv c4dj9G>ϜZʹ /'g>ԯڐ+RxޜlžZ[ާ=:oL"嗄Z;<]ݹ߽i}r$[<4a3b&^ջjn:CxȽ*Xe1sC_6cqhӛ/zӬ{ئŜU3r/o\7I1 %ҋUj~|{oQ ~L$TgY=/:.[}pi彚g>SZ;`OKpK3R'^un'prtoc۷:~k7{)K 0HMk*妳U"K3ũc4mV/wۨ3)3e_7wTmKMg~aZ{ozl=\eK;$};¹ +mo?K\0iϙs$X=TZ:>^uWL=Jy|; C\+;-ؘnоې/]ν픐O)sٜhκTqsx tEj-5 +XUM,,!9/EY\\@gm֗^Y.K}6UOqiQRzu0ufnj®ٟzJ a7}zJ(6?`ASo澮`cf왫n|nGG_*zVnzkĮɜݶsnewo9)Z濍/0_Q5NpW=]rƖ~}Z}_r$)'/O}}QIQwLR5ڙ{EnK6K?2"aO,odCfi׌WVYosĮ=*2׮QWג;^Lq5;-r.o3lIbǩ7.o.eD22c k-+sZݔ[w0`Z5ʊ/8*#ꬢD͋/p2#ւ.N[&]+y#w˅l=#~o=-3?qyDmO^eNԻ`y$n_tAv9O@n?p1عP`ή{fH͒cgBNZe',ޚ”qEUWMrFw֩O ֏(ӌ9VɺFe;yRsv+=ēn $ͯ]ktUW.. $8'mgۯoI~TGfј%K\X*ŃVL2&:ԦEa.3xpp>7yƹ%w_[T醵R_w7epMUg\"qe\[s9 Fmj?nywk0F[_g)ܝCU,_[ˑ+Lݿ(~&\jAՏSڧ}~uCVwi?N }˝}Νxʾٛ}Ɏ؂ox;bxO9Y%&ϗ~; z3F݇kqmJm^4K۲5T{+cYo·lSϚlP*r敎Շ?yFcenыH꤇S\<23uEѤX(1tZ̭mBޔ?ȿ=c"]j˪Ljx8CvngkL~dzn6uG3ߔO'KwTV97pk_d.3fSV>{oS޶PYya,eߏnJ9I*D|;Rȑ'폮Aoޛ?JdIٷ^bDm6/²ˊ}Ӝŵ[ay~FNԷȢE3֭~JKB_#~{rqsykމT~k*r9ûY6C?CX"|./>psNJ{nx)Nwfӏ/dS)b&to.9vY~>3/ ^{"q}r跽*ػXZfD/8i~AC}.Ws +V]<`fp6{%;-+LGZN%S>>nvXpeozs|gAyv$2[ofSt6sjm`*l2kk|$>rg-Xw[g]W8xpr{#%w +mݲWxdqoˉr1Wדƨs/\=e&&SfQ\KoUݓn}y1gD e竆~j?+OXƷջ;V܂?;_2NuP޼SVF%;Vl7٤fZ#+[Dn_ɉ Bo\3弣]ay6LDm ̃m.N~f2wUߕw.ocd_Yo].5yϣkFnzĺPBA?]\mnFz{MOgUOu]xh\S#={_YJWݝ#]>,ȖJݒݢ182~zv!7.}I9-M=o\޼'.:߶Ϸr6o4ެc߸dtˎOd5κ"g]˕/Օ\"҄o>O/"T6z$T^Q+mJq˴? =lQSwՃel? \hMD'Hc}YuO.Z[a0mcG)kkܽV֟<2f'8޾QFt$V8ٷmS%s^ZDM+ uȯyH7^6G}KyUƴ=7i0:c{u_4 C]w1=4f;Y=N>wlw:X;f[>_tJV^w#㌀{5ޚ_B5$#}%=̾ڐe-ǖ5[lx˽?E [Z;|b$[fn҆gv:А:ga{);}U/'/I{sXӶWpon9?.ƙjq|J}|̼naή]܅kws>'9F?֦|+&6bn } oǽYT+?rUj2G|ou;M6X)￳>7!Z.eTKꜞV+~2/ZSwkˎM{/Yk9ǟ!kw☉o_3WkxWr7ӗ:ړw?73L=pm Ǽ5o:xekVRoǮ֧<[fnf6STs4mrz`ʯ;neur_E`_+jH6cJu;wc..z)2wƗz*cٙ>}>fe,U>=&9a;$yMST +2umO3iƢ7QMDƠ ̣C~~WҢҷJ[. S&yy*.[+XiK[ǯLܪfO=ɍ <|j^m_O0i?v^}v-')ߴ^縩AWԳV"8G/_ck'>3|kuMW,:7O)b1]2+cu7=I!McT4<< +Լ^2-c✢]r +%jTܒynεu%l6wysF>ьn+W}n0u|t(IH> 5-cW|sGDIP'-m~Gs.GL슉SaWEx%""q[M3sɳx}骹!,[|k#W'Tڝk"bNwR.j:øJ@bv.Xɤ:|λ>8]b{3J襓AS[Ϲ/js9?uX5iMnL E];\fs\ 'pTW |30h_Z0Uo4åV3f]nKo6 +c`]θ> Qr欘[7](FLjѺ ^}f͜e'm;+RZsr:gI'i|}{`cmr&X>3ԟ1XΧm +Qָ"~?'e{tfu< +_s9]2^k1sa$e +յ"ϦCMwNs_ckoTGºj% +󋕿\S[r.~VP9*es% +WOM^zmwү3ULkK\[9:“gX\? m7ֶR<9ӹj 6쒛I֩g:;3W+Ԯ2C!ck^~rvkJacg05Xwgk B;N(P?9o"|~-έWJo2nӭeOjZ'> Zqz=϶0M_`am޻߻#7}<+ n[<]t{) jZrY-rM92圭!3U^1Sx!-fqNN-G?oqBfmwU3s7Xw +ܰ4SJ7;{ٴLR~ҡoә2|{=^bzפX}b kxxs"s؞l>rP O\un>6cM.wv.'hpʹӇ]vtU"emzYv>/p;ʤ?="ULJ[yaM7şpim=qSCN{elWX3&OWMfdu݊Uǯ.|f}/ +E,8!萆KnDٔ+Ȋl}bkE~"f $1G/d8beEa^9 +kl|`i:qEޚwxtx %re1~-T1C[c߯^L +;^y^wS5?b|lY^#f*ޔHK>DЅo{M>Z>ug0nU)\ +sy>&,ח|z{xjzVQjrfߙod(gQL+'N) cߜ˫vleHogN?5lYSEgt\ߞW|̽cO=H[P|ZKrj>-_r}F#{b^_r.o{3Ҩu\Y=,e|U:+N*_ҹ+`ͽf=xu>'>,t^+.8"f];:[u]O"k^8nlOTNZv֌OOm>hTM +oݙ;,<^g\žo*X0eZ'4*-jN~wQn֗%|Rƥ` d2[xiNԞf&3rWiE,"+-ܹC]ж wgm?*zF?f9^8MdUϹt'y=k&U gk[柮E,EOʋ<}&y.Z c =wlyiy~T®L>o\z-U9o25w<Ͻfo_mQl-g<}\lu"_o] +^y47i</D[{R|uD90xژ^:IPHE_@qiS-M >to~* aP9s.qڃ,kV{3ںT=ӟ o`u[j*%bԸчWz;{.*0eÏeIolI3_{G-;m}]g+~^~Aƺ 1s?[rceƹ|Xzúڋ[u97on,{-Y4Q[>F}/!bV_.:&MHyiK9** wnK93DO 6?p_)?Z<ݜJ˸&]V%xItL4AOdn{sÞ\Q>?w֫65gkSx_Ws;wu|nTO5Ǜ_y\_˞qf="ڔDnu^{Jfۘ-+f9) q`w&LO;ZpU^ؿSMōbei/rѿ/>{oc:wIe; BK,.\v'ckst\aպ%Vvgge=vXv%WWW?-6J*GBxi;+L0i:h ϟ8q%ty~3ZYJtV ϶!}xƤ>Y_'{D F~`c(S+z@n [{su`*]d˭{7(3< ! n+~oʔF9枽I ~O\%hy&Ok"otYs}̉7YV576{=_x_ƞsZ*i~tyExsps#(;_Kny@;/2kMh?[\+em5/Yp|찏\g,0EOl2ײoKm<)`Z ?͛Br8]}x'ϤEgbӊe~M\=ﴟoˤ#X#Vr_yn'3sMHwg}.OΩ&{=!sk7TI4[jݫm-5;TdOn=1eϵ5~_)"?KDk k4Fmn߯?Α\&H8毞CѕZJIUIu~μNm XUȷAg̖>I+1Wt}!2)MkV<7Xk=/$ɺg|l8!eeOn0>㻚d)3 u?uL)料UW/1.-\Zc%__뛕XWs?>sĹM!i&lV[^s1>{W|fmF)?ٸj+=A?J>^J=66e1[>[)@Y)So 8Wey4ə>Z{7j6YI#]?rʗZ>0 5sMLZ"qb}k;73ط-])ubb ]76$s> xi{S4a^;nY#=7pv4?zkQ̪"j<9jU?[j)a 5cg{LxwwaLmG?O9n!V3&Rl'3&DѯDo5_,vߏ`f\'(sek޹]y~͹^Yz)~Qd}a3wv-[붤%-.5,R_Z;Ob%?n8f|gXy/q=YݽoWͥ';JޞkH:%w*;nΘΗIyuS=hwpe46:yO.ڞ*Zxzq"޿v G6?~Ƕdi?=u7s߽QUsDv-[!~ZL&Oշ͏.NU7톟k.G{k\gOsY^T_UB']U:ܶZC'{^H Le/~r `fċH r]$c ?H{J5$1ƲF?81-/9KeÂAZ 7n1mxU=$̽cK\EEc<-? ^v4|P̍J1yO~jdUgXM_*oOn>eEf4u_uMA+'peNiʳ"ݮ{-gן*8(̞] })sy5Sͣe7g~$D%O^p8"<:f]yeΡ:fMke)b'0yI\%G+u1Jԋ׹ߦ7Y \ɋO=;_^}NԑI6? +w=EZXb}ٖؗYS-5xp 9k~2?bu.GB _o-n|%N{i{n~tCȢ'_Rz|||Ƃ{7N>Vs׮?\6BWN76^j3qwgJoQݺaٌ&Oşm>M_bVG1-ygVh%ے/]usk +3<{Hy~{q3y}'}١IWsElXIbfp=V}YE,],گ9vFyUS6kV-З:ջ&Nɫq6Yr6R7j[ZV;#v]%.| -֕w{W8em/|zv@ӌTLsfN=gN&_TO9nb:>{Ϳ2k usM}#IB+nI1\ӏo`}ˌ<~u_<_3K\?tm뜘iyRdS.iRON'EEF,P:@*:Ϥɸm;v ם^~-KWl>uf~W+hdSrhȗ37>cn1ǪZ,/[ɵ!8izKcMLsU_̘J/Z{˯޶[\wEQ萅';sשv`1d.!~.ӓEu~teάDkߘp2NrhCg#Z&\.13EXhK3TVlYD|7KOH{1eqz~)\]e78;a$\~63}s6i~{1k 5N{F|+vZ򪛦[{tmEƅ/bVysLcO\/|V>2{{#lOJ=[G>".~8uj׵ +Vj}\$}}|w$7Tտ?_|ֱӷ|Lpsn~RY빟Kiؐ v_+zw&*vo׋CQyַ/?[[53 Q6|f)PɻzDǝXod>n r%טj-4s!ZZqT%6چZ*#11ȏ_ή0asq/NjB5ͳ}fyy\n*VvMMq َ8mn K"K8KhM [N[IBϦu|/nw=k^F+GY_b£#;mťk-Ys\syӫǿxA)婏g;Wۭm?QȲi=t9k[h!JMKU( Q_h[@ ;NJaSwAlNwcon=ŝͺ#L$?\M/ʊ ,1^|SlX(}e.Ez4ul\dM%;5}2oWO9gxf8"΃s3d~6%w9ety\{<ž{}mTKNBy.UkvC<cϻz}ƞ'N{NG~ݼYpSk7=lS^4ڄ1yG[wa&OYgM/~W`G5WfY;1W'1{÷S-#k)'Jĭ]/%zs̩iӯ;}owmldK97kݎ_?FnY[>{Vg^}]?殼oƢrNW>,Z8q션Hm6 jΙZ>:$h+H%X^{&ɠJkAiG3:7eW@eW\mkѭx釶>ey2F /drR:-)AM +k`hj:I6o,oPkmU?ҪeyW<(T5aܛwɴ,'_|#']vDYu]k*]7ynRE]O&.]yc*"l皽}:/z{'7h g)Łk̴MYiVD/-m!qfOO?[*ixjk-EӍ=l7wOCW§)EAܬfo?<mvӱ. +~} +D %qz“_ +9MrŽwۙUx򮘫QŻrcB *>w-Wpw咖ޟb:,,bs2ǦVk =8\z7X3kUeSo–-T{?x.v?&)'dk6om<\cud..b89ԵᖢǓ} +k$x׶glfryk%,L43ؤ׺i;ֱTqT]Zbro&7I)6l?}kd1 Oz^ +&q81Gl{opnOf*.kKK . <}gUo_jft8uHw5RǶR:=?l?sU,(Rﮟ6Nc#>a/~İ_,ޯ.aʣ?bJ*݉94M{vt@WmxӚ2[%U+~XW)Hl_H^[~iZtd?Hn cuVFroX3aŭ*l^%/R٢ݝ.Zzk:UX?=7E-_z󙈮 [[y4[/qz[dLC*GE9{0*}M}Y+7ޜ+>l>R|1+:uH8ulUsW>JU鞧#讻vdŒ^m3 ~х .][nU$bne>"j~9KyƎ+fuR|x參U()7H1)sfSԶ+ݿukVrѳ?_!ue˧^_'snsˉ5i Q:Oy_m 4>U]dwRס𠳎W2޾Cݚ6z?TO%/X57l+W.:t7}QYӧo%.i5?vtB(r6_Ss0viS/;"VL;qW8|'|%;3 g훢r[sN?ɪmˬ/t.zzމZmqyBկZ^%'Ş}gO}Ң=Zlf,[(i=[Kn_phCM_[kӶ߼s-_ e)g'/4jt/[֔S7TꉫOo?GSS״ĭl(w>󱉗eL>U\"yYRe~&-~D7⇜yLn߾`,[?? + +њ?zJ8xys1FO7LЯ+/y@A֚j=|cnllj~]q>d -O^ ?+ؾteޛ]tӳcKo+3J˟2sTCŬ=Ď=+NYջG2ܞ{Yrڵ!ϗ?yzdUvW9Y.r8pტG;.|IOL3qbԚDlv (Wmi{ѭ}^YQ$#?ӹ% FV2yiu{_K鳳W{^>Wt*ߤ/;҂yҍ7GuTdHkNt 7ݟfMתt.Ok*p7Evma?F^^75p]<\EZ=reTha{v.9v(ᘋNE}YJbw](}!KSoZߒjUټ_[/ԉ?y^T O}B VOJ5/Wz%|ڧU=m׬vպZǜsbp= N?W.ƙr%U6 @ycwȒneZŽ o;ܙ +OƢIN\ߪz瞜coe?p߸:V?U87mٽbְT6.V*x%] gCn+N<| jM.z߳t{ذ?V~C`%3/뚵@7z F5YI,Fn%"'o^d3o![RB<}>s c?=`סp%[6+ꐓMoq]iLF3L`Na}+lu1v +¶nvhUTşGv4jϝ׎q2ߧ7 ߋY+{,E.X{2Pd_kgsY%4g^;pˇvS7p3O;Xt|_=V:[Al6;/VS0WRTRE"ϐ[GuGDžI_:4nfz}ץg&x\4=@{ ϋS.??K鞵:M:tש vIO;e1kS˷|M&^*1?\g]"r]5eǬ/(&Obko eg2v1֢w3#8d%ڽt|E`P_7p͙OZ-Bϟ,?GYX[C/~>gz썲%.igwN^Zѳb=/Cyқ~P@\~W?D*MJ}̳3J7g߈ξ{r&f+ Ki j$%/u9O~UL@Zԋ_ +-RSIwsi7;vǞh~ǣAr9 GC47VZ|i +SkS1_k5拏xmV ^i$m_$.:[w%Ε:G.;f%yp-Ok;MhU;.b»t֥ +سSoO8+J8s]O_2}5 ^U ;U彥Ddg {?9uTuѼ͒6ՠ]&/vͥB%վh +9Z/_U2O~fX[adY4ūʂJxG+E .RZs3tF&m+Q}s*vNxŖ/OM҇=)x9"j_󲜥ՍKm'n +4ҸKR'Tf9W:$6١+W2IûXUlV^`Ugړ6/9Ys/Wx̽PYX$ud5W$ל[籒q-!8_tgK?'uy!䊵&5q]*ZUͧ| :9)WLض}TIioW9从qI;5i<ʹ3~̙i Cn^**--?aηFZsˤh);N+qh)50Q̉F.ukpz2޶k s;?mЏ~}s^f:S>YɇR!!}Rr +g(ձPq$J1y4g{2S(h<,dkv巵nS[r7Dڑ.'.a?/tݥWE[2gv%WN9Ɲ[{bɑ) k˟^cՉgaf:BwK-fqPԬ_.ȳY:hS3Ɖ6j'U-\;hZl N*=xdҾ۔]ڧkV9u۷Lz= uo_]`{3 ^ܸ_;g{ sY(|ΰz +ޢ}:s߉ +_T4d9A9I3&3=)lUsc nYtZ~@#|zI 3d.A@u9>VȰsoyPݓ?o2 ˊiqhzM9LK|oWp=ey_؎j_tjS,w{|v}Esٽ{W^K-|1!TxQ Zg"Y,zqv}gvΫp宙|ު|5 =ェ"A`=8_\vjOFXb n1h;G:I#kzukƼt!,I?:[m$}>|Y:cQeC:*i/?,sq|xnE,ߗJ߈j|yдZyv5xQ UY _\$rƪbz:J I8oݴߚ_ {j;kt&y[q߿;\ӓg7.\%ldCW? +9SOGӆ_=bH0-bU87dk/wLyo'W;k.V3WҹZ]IDmw+},x]E^Gkm_`?0њ躓UBu7Oo/`jp}OR+7N|-MӤ1V?Vo-N-($L'&ۜ{󌁗vWBSNgȴ SkW=$'gўgr ZnZb%;?"i690Urv˰FXmמB3Om~zoCr;sj]-Py⋕.k^xyRɕ v6]L*/!CسǃZO~xveϜ{ͫfsg2H|av9 NQ;i {rK-6 "Y tM9iBL=ǹ2/xo^nj{[eПF3=8!ZLg#fso [&_~zfl׀=y~?-mN/T5qmW/8Eμ{9|OIlP-k u3aҍkr?;E#/OSF,9Mvk<_j4|ueow6޿@Y{>9RE3Q/n6[!yaO'ȼiKӷٮ2{žD7f+/'-\mwܣ[ͺ#K4uًwy:B95U7OާH~U.J|zti6+)Ḭyd䛓*Yy;kVbo~2fx5B38 M͸$~>/R{n"O/Wjxb]+L^s8v WlIϲ|lzE<<8k\|ˍj>|ΎCr' +Z +grTnzġr-%AEl9n6"s4^pO#"'6y^O+9f|bntҙswͼ]Mz}b be[}!}7v^m!H`ҵWSX 4}?7ɮy5G]y U|͙]&>z,#*\~עip<{x{liwFIEK؛d<9>jʇǯ +^iW$#gGm]+YW_>=}IULɒ¦z˟icuoѴ.4(O]N;a~wV9~Mbߞ y~E}K_`0QʌK2+;VdRmLӣ2-M3<>疒 b&Z:XZx\ɬ {ffUz$0Q|~A3.l~HYӕf%ݖuC}˪ Yusuj:jN\6e۾dزO[wEC"4ƢmzS-,XYLӆS~~m>.qnÕE*Ckמң.vWlw~,E7lN.ܐ?QfB\uy_5Yp3f%WL}wb&1;R2cJ}מ prvÂf^_㺺xk +|.sb4O7zYXɑtkʥj|^*Q3XzYG%jy^>ϋ6lA̹9W' ??'Dh[dDFj͸vnR&>W͆oSfУV0OU^ployXLu1w}Lسkv|߯"VM?rvKc)%ϸ.$-M԰Wz?Z, Ym4&uZǹ]"{|uxDq{WOܼ{rǷsG9rK+ǐ=η^`]yvgAs8/xtCtac6k ++o(m⬷g֕.-x lkXJlnub\.qʹߗOJx̱tQ+3|kJ/Z:GtzgYSmZ|Ik.wv#(kԎkdWd(Lᅨeۙ4~`V)m7twf_JT?[:JNk}E) +Sw*^h?uG O>;5 YgZ_ķa>3Vi{-]+_>,:IuGwlQjaϩ5/2~ _-{nw5]tg&|%?Sxncf˽jZZ0L]djVNol"=!/2ĩ0,].(7a  餆26'72YQkUQ̫k60j&74Lzxqӯ%aȣm}s\gZxNfwMigD>%RVE[U8Xd՞ +}:aȭ);f?2aa'G۞iŷ2eN W{ܠYQ>{z̘sxx}MSvRM>缬 I w_|Hňn|N|`j+[ Ӿnto{'?EJ~Q'ot^|FWnU49)9S2w\BfYj<`OWI,׽]eGv~o6=󛻝oꯕy21%X&ul,YnmN\,psDcݜ?M7~p +5tzyI'Y'jmM2߯ +J\~μ&rL7lNr_Dڗm.5wfn ܘٙIӂV8z_\~#nu"Y #/LL[=A_B~#/@yuXOVZhWji|PV3QRNg{_-~-y-]W8q=:cH+\;;oϚ ?1^!7dÁ77μ}h-WT94i}<ٗdz6E@nuxF35[-fЎ=%ˡU'dϽ,1u]eUyV8^ab+zݖ>iJ[U>>q/} \vL8LL2h<9 gO}y|w+l[gKgKr76S+itgFǍ58K&X1jȽ2OĖm/t&Y=mN"7GLhoc\Q/Jk 踠M։.S^}hn + A,g_yKǃrFH xQue-1_zڪSj.l%yϽ-o*vt\třʫ;_ Ҽ*7̮q⍶;?ZIL =!k s~Yhޖe+Xl22;ଠxަuJ1& +ߝD(5fWs]1"\]t*N}[&qWs=tӊ:]z+npIҲj]ƙ~X>yv*{-͓_3.d^{] Am__0/!\Uwuo}tW)GVN>YR;\1v˧j&PН}\u Q9ץLzsQr]+w]Ңu5iW8V6\u7`n;ͭ^3jXy~˯OA1?ވ9$d:OWIN:F?\m۷OE3TynXx`H_l6 > +j;ʘ_7+&}=8Ik3rr{to +P1oFo#nJ(+wNy׳x/9̺_W|O;%6=ȨՁs]} N|:` ֓?-Hg{p?dRׇynWn#s~Nm,u}aZ^"3<,LXUPPUS-7MNɞP1-ɢzm n>q-afA*weXƕ۾ٹPVgI}!\ ]48vLn{]`Qǻ;7)hZ*P=Q';xY+{Ҟ]祕|;Hβ'm^/!+V?.P |]dfZwsԼؚwt9f;oOʡ7l( +( :mF:ҦofcNi IO9K&f }ϐނ; t%s4;Xu;yr& 5Us=%u{ڲ2-˚6v;>EnJp퍻oiq=uoqOo~&-}vq,Ȅ{7|zħf/%|l7/ouF6666f?Tҝ>AXx;AQk睭n{KeRSgO09qW9{| /-xk<2XG$î/W +w_K23_&Zn8돶\bu%Uـ-GoYF8S.0V+?\0h[E gmg⴪ၝ|}/k뜷{<|@?IkqFzIpƠ7wkv<7Q;ce +/mN啕kҕ<1_cEJfKx<Bj~Ni w7=/yTɛ<=۾1)ulw~wOd$l0)Y_nFu'f0aˌe/w~z,u˾ٶRʟ=~x޳ڽieLe2pfXxіXNA3~Hw>t oVJöKJה4iPyƧo~)q)*d-}{穀v* +mND}Ro)âd>2,${ewי3+>YQ͢]4Κv[s:|~ח)7uAKZvƒw&}+KKo7;$vdWW-ܠ1Ď_6raBd=g>tƺlq{g.z:u7diiT}~&xlֱ֏[l%`wi iU>t2rڽ\ '>^0,cBlGSW9 oKsܛ:N/?nغ씤߱ /ͫZjf]5[mkmYz{o?xv)k7ڰdqJJ{ ?ݥqWǭ.~`kU-\WxemۦSshʵ#ߨ_&p4anבśB.>}e:?~̨׳/Lt?9vW:Meb .Lh@>WS5']v]լBlUo=\)BT:]9BR2s1WkR._^>YTv/;zynkj9GKrU_/#R5+*V/tMS/l3BnK_ ?,*slu;^Q(G)⤖jN-N}=UZ# {59V7co[ٌ2-D:fhʁ =խ_lw;tgebNmɄ^ྣ!_;Ur|܊# +hOXp|r/߈T"Ty7;[cz o˕W)͑^qU4|3zfvpȿ=z*m(^[fZ EyDu}|;QK>2&RWfrzYu_Ut^iY0ސ֡]~l*{A9ٙF.qjr3ӥ&MN=[PPbcF]u߇EϖzxY,'OP8X W|fwd('S侱b]줳y]ʿ/4@V1j庳Akm9#-{=_p~O];WMUV]ƹޑ&z+vYlOt`||PfQˋԴn#Orf]3˝uUS68rpřsV>5Lк wʨ8E[.oyL7i]rW0}x:cFK;4Rz-1Or=|QGJ봩 V= :qbSL/"eg% i%N'Ekr ^vnl)U7,x"seqp>,_|YpOQhVDz) n0*-X99\ +Ȥ,6ueYZV[}sIZmתuHm*S.2Jr^5}[fjX7 8 [vx h4_?Aƕs٥cB'b϶FԯW;sۗկwooJω:z.\Iz!nj׈UǬ=oX|}Zy/r9(w+R|Ug#?"5NTX+QX`]>u{ "rׇ>k7+=UaeY׉*L+^`i3wŃLXu@FdSꏭ{~qh"}۾Mę^>u48aڪ4)\9fł /m by[$ezIzRdpߎEšs^,gf=٢KdիJ~}۾Wujx$gYCʿJ~ۺj}Kש̻ג}{OYfva?:^=lZ޼8)s^7yx5FAte6+f}f]d{y*(6a㳍?f@.os=μW8-׋ՖϏSDx7x$M*4R-X%-HqMv_;ێ-]+դ+؝E*Zi{#mxMZ+}ոϷŻY&904,.Y[#jʿWh|]tf+]#?5_xIVJ3Kg^T{_︝ó82>=bKRk^ߟ{f ս2p}"3$+hcU/5I(W?=WtwJy{M(RjNph+oJN~o!Ƅi{W-;Pi" mq:vdߗOz/➳ ݯv|'NSNkwݨ+pc9_sozippRέOj~ _#Ʌ/*SPַfEYk@gcLr?prlCJ9Z2^; .|jٻH`S:ź$6EGe=o'2w_@pԲ˷~[E>}TX,/xYUXSGkM;7~u{B*3R*pg~W5cN.Bޜ?GgFTo%އvh8z롒f$<4^+Z4&=`[3}>YSޚ o{<YԒW}Sz~qZK#ʏZ/d|y`uqlpDWǼg3͎V:9:˒۫6tjph>l wEMϠ?U^[V +x`ӟ'[-ڼ|i"S ^7~0+$z&LyJ- W:/Zɣ"ع4㮷,#'?JJ.jJr'l&'Uȧyǯkg>&a3m#^I} :Uw0z*`VI<Zm|UkW-ڜ y~鄽/-bN$ozt[*g֟m&jsUG3̿'鑷Fܟy˞Mvxٵe]ЂW _[xCzu/1)T1&=z&O_5[#] !9['jZH6t^xQʢmc1ŇrM=U +U]=) YL=yARd 7^t\>wҌL^Z 7V}|:j"ĿnE6+4jNVvMJճq[q)9Y-~վae7*7cMkBIѓ/}.R;_rF~";`sykze:sv6!f?.5VN2.+/o>%C-s2Wfp&2d_lQaUG\+?P?Ko>7BiU8Q-f]?Ml78; Iۼ\<3ݎmxEզ^3@5Ums@F}5Ovf~_~ӧsc{bmOM;ưz%`f"pƠ_l٥ʳHe6U+xTѫzfOEhxV Nl >Q9;gm7JΠy[K2ReݒA}Y1(ۻfطZGv^h9~qov/D6{ +'~[LN+HtAgEsV-ϾL\-.%SS|”3 <2ZMry~^oI}8Sw͚"-2URܿ|-jBeiLŭ+'n=[IJoM]RW{yx򃲋 /|sXxoܾ3酪"dlㆂڲXuDgIK9StްZxK;enѶ~{s퀷M.馰(/t8T]6\Fb!ӗ2oy:LNOseuqW]p +c=/ P{dnOnlBEh`\8˹'ޅw,{, y|r'[M,~v_!TKwontǵ4NqY̻;DW00ϑ57}ZK$֪ܗw6^}le\P &bpўkNؼRfo;CO6 e񶷹_PG@Nf&+ VFs/+6e?u{=PIź35), e41֘/}sei&8̞ӴM`q>ݴXIO~2\3:q2|%G-Wz"bP11%Jn<7Zon,ό8{Q`_m5sS.g s*)8^rY\67v[}wiogaLډK[k'ۗkL%C'y3gTnԈ)wJ>8mws56_iy'!G&T^5&d\j#,m5hKGZ̟ Uy@{ۮf-+Z~CkY~wŧF9|;#SƬ7IU>09 dVݭؔsVxoL嗾NOݻ}TDg?&/4μϒv|1JO{NNln9&f>3S?dMIr*/\FfʶNռqUJfMy>]֬ÖY/'iʪFVs_7svR;_.ߞps_\ ZmdfAd +)l 9/2Kdڙ# ?)åzN 3v5-*M]:eL^%ېiy2kMrVKYVSR|:z?>b[ѳyK*wS70eX0nf?%O_-L,~Y23sM|Uvn?:ܺpz3"9^dlUnXw>.xV +]#098k]ۯF:˿Zr{j:,ZU{۲ׂ+nq|,{.hGޫgȾW{Aփol/}=7h9*zK2psZϑ7Ik|Z?霗rwOͼ쑼1b^.aUPfg܄e/zK=qE%vJ6|cpe%^W0-~|M7B17dwN(-mxZ7oH=+ݕrcGvٷb#{>ҰIS.t<*{{܉ܲN%:ח?O蒤;~! Бcȍ'&M V59[gGIZ3_hK/T;TFs.N֩p5Dv| AȼuVgg^R\=;wx]=D~+ʣB'L3^Ӳ滃Nϙ2g'ԔӺ=rզ?w."l+{&?Eւ69|`ᆭ vY.7AQMᓕKh鶮2\i}_vO3{4.{癵8:OT+^%c z)^g@g6{>. Z$;wY^+L.ev115bƟ'~57\} m3|˥6I^+{"$ټٶ_YwBvEj 2r }T+mRG%(ַYa2Zw_vUl'z5O`S:{_Ns9{2.~C Fl(+h0IcݦO+*U\&r}}sZ9@W !;3t?߷}wwk}WHhЋNx罳O6 JĻgє_R|x5<~wsۗ=03|r爼hɝON/mYR֊ ݉Y|؋6P36?)cZVOk# VĬ#gf;mjg5o< L^r,|ZܮjZϮ%Ue-S*O=2LtHDH0y ¥KW,i\}򮥭/8޻9oŪ{^[‚=lf1yN7/UO3g=*{6pU#m)SN}ǮqiHՔº%}%-|y\[/0x/bxvWΩm}wOg/j?mhy_ڢH,'`yrʇҚf|o흼M՟4Y޷?39Dro[͹l:/M-}ߛJSn:>qR}sgL6"l{Z+xO$9Ǘ+|wgt NgQL/7qjPkIufQ$NTୄ%Ŋ/s?Z'l c#Bz>?1M5{?bέ| / +Ioer[63"&GhuJjcſ|:sǞܺʫ^u"SN꟟hw}IgӝRɮ>Qwt3x1#9beur` /y$1"v ecᕾW%ܧ~\W |-vCS{S_}ݷr{޿`u3/BaI)eK~W7m[i^Vl-c]/)M`bz©e_54__z5jٙ{o/ Dmo+?ՍmլrxI M֙ͳFmۚ=Of<|T=Gfz˒$L~)ל/:L"KB-WSlռEm\_/NJ{vN>JRvS?X _?v7So7m?zVSSg7xjK|.*G4Z&|A)S1{|;Oh!mpQ)Cڊ-19 ֆe ʖ:%УZw)B}V_{Q~ե- \~_LtaMnb-h `]Wb hwAB֌#箓+M_E9mcd\}3 N\,SxD2Ne5zOI74(ńi\q~rnmvIٶ$aہW> 8?mv_⾲m9=_Y߰~y{-J|~KyOןw!nT3/}ţ-Ԕa9ls '#3Bտo(~ԴtcvMލſk3|wd<.ǽdk;Xۛ/W̏|h@NބYos-,zL󎿏XJȊGP{yrvmc^b-#dMzgUl_L<#4mEgDg +>GxZmќqBi/~~4| WOL ;0۝O!=Fp)6lR-},~|OمljqK=+E[TQZgBM={o׻460MfΎ|d:7{Jf_Ōm~7-|mZv_5tŎM/ vJL7P5vwþ{#=>ݡ峸-}?n׻~elS[/杊ͼ3fY8~STWDuAm_vNf 5L'>Hb~MȮ >*?β](yǺu߽cjo6Yi:qpX/eI$h?YqqN7OF:}DV銲ZI7/,Ssg{oۏ7ܳ‘Y]tho6)qq1%nvR`JDoR+8v}DŽĉ,vOP0UՈj'-dd6OV=4͙^^&`A Xx {|?zI͐&W7 +./xңׇ%ֳ/zol,2bLi +[cڧ*|}.pW#/Ns8Ss&'{5#z:Yv(?KM>Χ}O=ؼ^ၿlLζTzZ?~\Ye+6LzijS2gseOO4];b+ߖ", +]n`6ާhMyӶ-W6[u L_UT!8޴' ,/ZvuB~3_]ۡFokNIəT]H-Ql̷+Ӟ |S[NeYo}1;w}es +].OJ5XRWYp٦?ޗZJ8yWyrp<'-T yT/μ2k|T;ej/n>`&NDáT;3fB!{Wʹue1ߩȱvYqfc.K9b`r0 +g!;r~9\S wx]8o_~12Wƌo9*IpȆ᫼'ߙ:񭣑I׏[.\y1FU +7#3?Y"Okgʶٮ4M?wq}ӧ}򪻝xMrY6G;^}u5f.fܭ6˯timcve]d/1q+g=qZu_% Ϲ's֞ Ӽsͧ\f~Y\gJL7O5{N oZ +{ukszD`b{.GxU؜ѾBMeY׽eJP8zN|qdJ} 9enЖ3'>>_S&6u6ܿCz?ٿhmT'̺T͇3_buFx%>2S\ϊ2]{b˯?JkaTdU$LGZ\Tge*4ڜ%%JsS\6^)&O9嗑^7Ө9N}$*WvDu뱋=nûw>ăo~[RT;γo +?g;ug9g/#/_|bi,ͯi/lqDŽn!lVI[76rغF><=٧$~kj!@3|2^~D V}ьw9=9]ps瑭ς>p}clh1aT7isv[[Fz݅b6e݉F73i9&#kna[f.碑V87`Cg}~T}Puۂ"|)vV|ݳy2w>x[IF0}rIMME·&3MqZl~sve=FQUFi%'D>muL<9)_fx?rg6.|/t?3{..\zO䳕7\dNbܵK;~^]8]]Y\q侴N!GrԿWmW\KͼcZD?lzξ}IU:̹6[>w*L&N['pcW㟥4.7T`OlvUӎ\23(bG{W5UϽ5}B_>*wZ(LTQyV}r'i/L~B;,nKε4mߜ\'Eq|fRU r 7>L[Ų-5o=Y&b +X/R mƴksNs|IX_Dl-և;7.>zv{U{.=u>l{en{v݌-utsMVzGeĹq9da+-5%.z?>s{dT7x22asvt)zY8YvEݱ 9u6fkW\ng*SCE3h՗hh1U{kuN7.+Pԑ̭:yCCOtK5)иԤR#J?c>nӬengnqIr6;uB YװRŪ-ܛg3*y൚ ͻU|$XZ&4N+"'vx=fU=)8ʿ=/3I^4Қw:2Z?e_{]nòp >+}7̊&nOi<9#C,B .s8rjf;S 7Y~ۭ=ݕw⍙V_ޝ|%lT;Gz-حr~W3= +ܩ'X2c_|n,?-&Ϯ+ꅻe^ؿ]99-E+ޚ3ϽRϚ9,s[H'Ccem~]T}#qsC/ R"+{y>eIPΜk=q?.^hc7WXL5LLdqm>s 3{VU\Ϧ?W,>ƅxV.}j=|JzzBa\"mnđ+68&Xwg>3ri:&QlvsǙsbܱ7z|f Ⱥ| O1mTrkf{u{* +ZhskVf@墻f|C΀>1 }z8ʷ31VT=xDNF}zmijo>~j n)2Zw>5I7yqƣS,oufmwt]v8V5R5,M1]U6Q]bs;ﺕR5n:~xT&}eˁ{N{y\v?[W<]|M1Ѿ_ż]f[ܶ;ק}ƔW˩WN_TSEcFϧI L\geV}J-gB֭ a@|{'b +jENek;mL'[Lw}F_'GeU-O:+|'G{p6_>7\;zN|\~ +^<ͩ=3Tg}d<}Hu9CpaE %Yv`1⼈)s?|xynt$P|K!#&Gmsp.4w}#/|.{ޮIꅉf%<߬Ttne;ÿrfK쩤̬;]7\~jyX5 +ܼ ]c:4\nev:߼w6Krԅr0FfcJKNR>vt[.s=/w餠3,˔Y$ܸcw'ϝZXpƝ3X.//mr[Y/JYU}OuT׼y9 +7K,=n[^5EDhܳR7PMvnx#o +]"6W+t]3,[oEh_/$XwLc/ +tO_W]0)gW$o>Kfp*ymSV)yKDs^Iyovh[GZCe.FY0qN#qxngS?/ M~ޣNL+&ѰF#0cQo/r;fk1𗑩RM3x_y^Cе>1 I +hp ]N4wss g#NYyvx˓bWNխKcr?x/pUhƺIw_5FHv4Y}ҳ4 )GWg'GS]~prj{MLcZ\3D1$eE]d$i{/ 0uLY{(ϏK\\gWU%vR P2_74@߈mGq +O_7bU;joz6[sv--x'CufPԄm\޼wa!K6S3^zʭgo?lN7eS+_c|cv-eB֭H6qyҿZ_^~A~WKHZ;KV|8xOHŲO7R{u_9+NNz̝ntRP??K 7ѳh5 +%ߴ͏VΎt +ee)Tr[Sr_4UY&paq>ؙUcьbЖ㚬x¾t6s-[WR_xtrΚ;/ߟO婕:l{%v.Soïu?w%[&Q̔>>oC5[\5T=5#-i9ˬ&9iΗKʻ4ܰOѣRƂ EqT6V%GOۓ{JT:MaTklcecCzvl鞽 b(Ypo}DnKhD)3Wm=׮PG7:~h9nh[ /Ŭ271s$Šei)mP + l[WnrSIcRx7,(_:v=w\2}횷<.hP$+_\jfEDgjc 7וj{Zߺ+\32w>XJߩ2z܄Wo0%HWMWJ>$>T a|'9TwVz Wnr?xqC;-_g[_k~q&Ӟe&^V8IVΠ>lz߄rQSxboNXqNΒut5ᅳ#fw e +v;ֺ]6Df(`>~OG6g%6?wv%r +g{^r7&NРv┉U]㬟G:6pӋb)Nu|G=8_TEW ld{,\sĠ4|F}N`\jQ׻GNWb[yz/{"=<.ycJvc!MG扔]13:̽jJp*W|W֪'׬vwpU‰1" 9T5u=Qa)M\W?hYjU0Y\N3};f#WS&2}jXYIC//>ץ{dU7[E?%z^AuKy^<~bK^W_]stoDm,=s_&xXm^;==Njz-}W]5ҹ*Rւ=R:">H qbIJy WeVZqŷJDړ%=n[Di=9=/$/ps=?ke9xLtbxc6W3V^|D˷+NkNr\|bkۧ/Sq+%xgl?lnz(I ܞa⽯g,YnsѳԆCӓ~:[/DVu3W@O}ѵ7\(Єw%m9wznpsS{{XϏ1K'ܘiɣc:OL蘽dqSyo^x/޻-Z y,6΄Jlf{3Ty3 ϟOԳ·{Z/D9yN.7Q.r,2:;]awsm\ m ,djhw(pgZduƷxˇs2nO7\Y_O_L0{IWBgFܓXZhi~|ŋSrCnhH&{C=+wmrxЫ+&p]L;jΑU'nc߰e%q&9YwZovD UGae;DVXv2Iy{cV1=ʝ cݺy"/>,Ufku'~XjnBsNr"7i[nj-Sz?ꪒbSel :ÆyK +W>X1jDۜOw?fop6gTߑc-nw raWGk:^ŌeSS~Zf<ҴDTK4=!=]*}Q[:"xF46y_l~DY\i~MDM)={4yNխ絭kE\;^Bsj^>OpUʨKaUdU*U7tN6TySqF+sV뢝-Dͺ.,en|lҧ.sռBܣtB/'HG׾7o5r=?+6U~|swzy^*wv s#vWݨ3eM6oh9A-<1Wg7Zu a:5wK,.B)j2h~W[n?.QEu'WeV~T2eD'bfו >]g@5E%o˶HeoralKzz 93ΟwҎ5;-H?E7 cOce^-y1r^-HSMC:)oue/ I^YKSbq8_t`޽֗;N{;xCg +m'4a?"}a伙uwиU\us5%ٟ + +}i3J{S7KO/P_mWyrn_*[w͞0##!aOm}U\i`gºie{z_"pOo {*JݜqњݡseJrHi?:b@9W]+?ov n~ d>Q[WH6m//jy¹ޓjbZ,½\BD^tK6>&lPuMxiD\pԂBwF [[?'tՔ˾Dcƻ>l_ӮJKg'W^S)ϿGW"Yf;K]~FJe}]qqǁқm~<0s+fo7غ짐ʅ;2ˮ0:,t竧nKfYH|}j;CiDw>tl#Zဝ; /+[~{*͗wJ3rkhEczgr3nJ~5၏qt +;EO~{~׸k5ۺ=T\yY_WNK]~8ͳj6ZF ]ξco3{<3?),|W#߳:Mߏ_.&8Ӳ0 kS~_~BiV׶/T-|/_=zmI܌1h[q{kŮ>vfYPſg;~ljwE e~yb=I}_IOeg\tLNt.(]K9Tc=ՂVn]k^)*WŞ͛rm矦2n{Ok޼k^Z[Xe,vּ؂5Z4fo|<{} ]/S%WU</MiZe?;-3,8sᖣmOvs>jͼ=SJH>m'UFIRuT_wɑ=*ѷm|̞)?ZYKI۷pDgr,:.K~{KFe݉ $/95Nov0y9ZT(caR\3O+yknO]5AFe~D;Hn7,R8̰i}M5~i|16Xh.Ǻ9nFŧN,x,iAW7.⁙'XI`\|KfQ틛6 BfolӽwTt=!+;^̕6ܰZ_|Z%S͸T$Ǯ~W' fY!c_ʭjY9ɇ[_^fmμpQ?6ls<:"Vgb8bĪArő@iC٧MPMf,ds} u +Y-kgU7F~Z_bd׍oUJۥb**nRxvX+c{>;q;;=뎀w{@}iy9u$'VmZ V54ۮtOXO _ė4bߟrs\/{Z~\d*W^-qf.?wyiTAj&6D]2..^11B#7VUZKLS7bNLt~Yn  +?a9/gw;8=M4T0>b1QrFy+W>q7!JXWW~_9ʵ_[~.+'ZKzdSܱ)׫ "zv?2?9~oYF7DVvln[sԙWrMAVj$ Lӻ/sSn\yc},cڲr`Ig;n_fz~Q>|)|9}515H?>Nq)m#?o̭!ɟvL~jf+O"7mio\uswKVv^ o^?iWdi≎a /=?QkZkg>e^yixْ5K?>Y6{~2` +ȩy9CkXx9I^R3_s!k s3Z=kQj3tu<tWqpśْ>3^8VR5mE{2^o|yGω 40x#90%u\鬰Ss㪹o,ԏII?fW{Q7j OY:c³;V_g2WL|rqzAuکа+~άF}q_O{|&L YVZY0a~}Z3;wfuk|ROիW{nSM +緥,{~ow'81%I uO()j)yp~(i˫ga=+{s37x.] ن=Rӧ5L^?q^H6'O]UZX{*|W ywMun_M I`J_kSg}5?3Kxio߅eQ<_۷J> 컻U;N[-;S@{zsS[u yfҤmPaMGom_F_MuL 6`Ѷ/o>+-T;*v][|ۂ3*WX[۸Ehvkl%;Or^μ׏_gN۬:rwSTޏ_'۶n5|+sZ&l ]9-{:|ӞI?kgc1:O.ui_eQ^W/᫿LrƄ3 i6g`ܫ/o\Ԋ_CZgO㺿~Xua7Kێ:5~n,˅ Mf%Uw|Ce' ;dSgϓ˾}oiM²sK3dpg +Vq]2M>#sM>/+F_ 2>|)4uS>Zĥ27Z}2]YSm +SD";g:oGkoN2tQ15> qx'JnW~t zh O̵_Jif.$%15ʊy4JaͲyݭ 7ubM;}og)Ex.ڧ:9 'DM}gz!ei]+=13n'_?p̓_V-]ŶUSŭ]3E:ΛЂO+N]zaV·3s>}y:_,ϢY X]m"{VlKՁcOg9>gU)=]yJv/̫ceEL}|/m깻W;ZwSecY _~ [~۸E{ G_Ls^TWMRzĸqMYb7Ȫ[MMfoq~Sh˟Ex Ut<ֿw>zDTyk;WJ^ubpܟ5$rUʎ-/yNԏž%Xt;79YYCm=;,>3m 25&dp\y'NiMgIO*R6ŋnokt8[?ܒmDW*Ώq +۔kXM*-/oL|c? 7+iev^=A'jKO*ۓO=cZ3KN?ӷo*}~Fݟԝ.$⢶T23GMR#nM,[0Nt21Ϗ}kHgau&YWlRx~Lda_r]{~aêYлXr*5t/n9U>Z^,Wj +1G5G6m,,{_o_cAETZܻ_{K-d98S`x+񒾂9sJs#O/OKX50v)*<٪ &nЩ;IuE. ~M}1uGB_fN/^ɡMW=`^f?zC躢W ~yăE*s\ڞnnNCe3& =;N4vc6S7~BsJ?;O=w.;Y|7z{̖߷gI-nU᛿{g2b. z~7{'ϯQ.uF󸎺364w{`.3E_grSwmɐٯu\.8|ҩ{TDצ>LZ}JKhq}Q{.<[.n?k6cUzu}˅M d'u f{q7Ol5QKmvHح; 2ݑgv/_iq(ԌYμA/3拡`.'3,UNroz9S~,k!}v]ؚߩm(V45q܂ +9o>ܬa[tZ礃v˦Emf{d3Ϲ Frȼd*ifuz++R9YOF0w 5#tKRm4PG O,~sOI^Vy'5'E"[N +)V|v(ʒ9IlF7湳WZfc:Wowx?ESi ê}7aASV6}f`|³GtJ2{妦so79HԏJ4?fŧ+ +f4"xyl›@mDĄҰW~Q=8gJ')S^YD`V ɛZ6p[aŝh0kfs,S{vٻ|mح%Wg0U)&B?qe"\K([Yo%|Glrvwgy^+Xk6k=e:ҥȨMoɹ]RI8Ӿ7pL '%۝mԇūoidsf se<9Rˬd&=e1L-H,[1fy4 >_x0w+֏w6>>guYwKd/Lu|Ŝ8c,*-aҳmiO\-X$YnMҴC䳱%*gzB?oxD5ԕ߷^sB+QßF1TDγ~ä"Wc:`^/{TWC+r=7ܱ[y|f 1ͱyDzR-3=*=>2;_xx}i]i[c?]3R}>Jq7*͜)ű6:#EVf<8Vĺ<?f{׌s>?8SPqG5ISr,*)=~͂>U|űru)O딒Zͤ2=6#tA*oVg{d{golV]zpF9ox^oUv=gvM׏bf_~s_^ +⡫̴9=$BםwE`[@זH)38two0{-)׊gz1b g v/ݼA[mA^zp+,׼+^)0$E;$c_?v[Rܳ=asq3 IbN2|B'/p<]&ޗ3|ֽo|,#e/횠e7kS˰drdɡǖ^-1;v_anb["LIѿn_vllRSX.!-KsUC- }r}h>eN#/0yU52{'Is+Yxsi3/$Ki flbthzm +޳N #%o歙r4@S2I>=+DDz;dz#RnV&U,{Ŷp~;5bZR=ZK EWԞ?qMy3DO]h-s[їd6s ~P1JknNK@`^D즜[zj/-=>{A֍9gu/^y3dRTso`X%zM;sdzmiUzFuV:7 s#oD.e/lqm=U<{4G:EH•󦯻lOKlf𩼫3%Fwӳ;,gdRJ]6]tQҥ?k vf]wҸ`m6xY?\a2'<9?I]xQ3*Gm'|cBcwVwQ4 9VgZXz⌃UseD o?ٛ 簒eg, H,oWjӫG~7x5Dw 2|8ݒ+{NetaDa64 ;xLwjz/(1(Wi-aU+=? '.:=s?~/{eݓ鿾G,|{Azbk>K{(nF6w,f +ׯL7EM;ӌߤM\+aʖ~mzmkZ-̿˜3SXk_+4D_^tYҗ?[seؿ=Á$|:9u*uu]josGDjڑ宵ޮg\\y}y<lc߭~4m9!wlÉlbfa=s<J]$9}A|[0O * qSWfιͺX`4OSchWY=\*ek3wZXojӽWpMvxlN"]''X}< +kʯv Zѷ/gWmx0&8e.YENvIq,&?O CdmĂ({ZI\l'ӧ"]Ih DŽf]k߯h;b[#dʹݛ~*7]%xAu#mVp?o<`mo۾m/SIL{WՏ[߾`뮈ݬӖ6x%O.t}oYNw ӫb_zarbm%=\rҝ׶ܼpgREU{ss5zVXS8}6gCV/]Mlq,xZ[wtӣ~ەj]v헺/6@fIb[YA6M{pա?ݶl~觵|(2 nPxQhU7 LߋL YąK]~=W.ETxVٓpwɵGҚi2kE]cZYqjk윳L=wn9:7Ͱ5,C >nӥǔ67O{wXlNﷵ[ 6gS3mUt;\ߧqnq4K7 b;1@U]Ɠ>q,s{U)u`ܜI>g7x_^r8.&Kf`Ӽѳ!ɓ:3&yƪ[LP؝ޫRLs,w-8po%ͪZ;+s.NasuW]\rє嵗v^$h?+N-̕-/ɋekUcQP)_h#tUtAĕ:]/{M7n Y~mvY! Q_=z𵰚IIS-NGG3Ena_Lŝm9A1e^eqb%^-:w{ԯ,h~yjԙӽ_6)ri{V2׽#);4Sès6ܧqm7DŽ_/[ycΖLKf[{ˎ/Tl(XZnBr۱ZfN7Gfvl1{gl\EgD':| L>㳒_/lU;gͧߟiA)O]X^ k:y yr,sW's;+@5ӗ͹scu+ yL_nc6Jo毗vt?˧g˾ӣsv: z㓅Ub- K>d?c.~>=J-+*oop<njz 4NTxdft'FY׃l]c֞3uw3L>tqةGuV ;R5?gDNߖhܔҿ7zcɩw$ҶbƳ cݝ,YN._'{ʶ9.mzIի'4678$c6ٶ^dz'o4V7B<}mqȏǙܻwt_sbL*_`,l-xҊo=aq +I2׮l߫n2ov*?WtFi N,Oך_NO³;,Xw,=yM,ѐe2G^09&pO=qg›\ܑiC1GO_ru1MfSҘ+о,mO*Ƕo3 kYwzܗ1Q-7mWݽҷU||]gW}7:c;&wlj7QhejPUr,p5UXTWh[s~mu8y` + +GGϜ<܍sEų[|XⰃFAǑ&Q7WΙ=mu2XkWXVcQqw#^.\Mgm8m#1=pE+_QkX+;eĽ ?)Rd Zys-2IR&).+*QpZ`)?V% zNeע/=kfIU`y]){cO#}#ayG},-^S?-ںF(iחk],&xpkt`DBUIWɱ,42նv:,oƪiYE]tP2fٝP}.dtzw̾}bZ_r&EUn 5L1{zO,ZS_icڵʄ5_F~>5MbƖ7gB'vyX/07]#K:傯~EWyrr٧WOo;=QkG6bonREۚ军ˏL9u:^l6~sޜ}}+*x-hMI׾Xi\Yz^ev߾{sk:7;>nCy٧>q'¶Z~\nE'o燖nZTtgכu;_XĻWo˩ *N1|s? yf_ksm ?&tǽ~qY7Ob;_ĴIσv],pCg@썥5{lW8SOُJVSerT@&y_-6#7"Vjoymˬ\66 NzOCLH,CnBwLnf5Jp}Ϗ#ϔWj} D?hIÂ5 W4 Gs*{.qf=Cߓ侞chlVK7=-\צT]|M;f/t|\ů \.b.Ҙ}J5>&3>ǘU>?zsSSjblSիdW;~[q+{ON9_N=vݴ-p9uZً;>=i,K`%x_.'\]%fױ.nYFǕK\vh{%`wH}J7~s\v3Cc-^R猾Oqw +ga_}ce#9+*m/-(;gԛ-I?k' +1ѢM^mgZݕ[YB +f;a5 _y.f:aȮ;ж̟bBc+#O#ikkkLi=~nJszkFu^A1[*POd SUs 271)Krł: VŋWzS:wz)}QR͙m\zafki~}% +u8q|r->rJ5*c Z&L1%_[T鞪9*pߑuvǢ]nliW֢M.P2ˉǚ;gj|<$Ao^{{=<\PU#潑=sN)zh5IoQj)YW_M?YvE{ީ%vQ:%m%\>hkWz4 k:$,}=fBH5GiuwQ-w3ߕr[cji q#q!㼢)܏Ԟ=!rSNr!喎rq?}տ0E'jcbҁYib o~_}{+n8u%.KV|{dUu{Đ'LK7?~w=L~N)-5-EQƍ>n등{{ds5Z =Lo-+]3cy9ؕOqdi*5N1Nb8AW{6h|j6;X=K(紎 +`#e#ɲĸi ?7ߤn!ub-u?u)sgx/q+YZY1lJs-8gY/pl:l.`*godŤo7su\ qc +O*Mssmock/TNʳ: [ jLvjSG"K7Vؿ=sop% qrg2f*W:/uʝq.x2wmYmL|o$ͥEz#Gj篘Yr̲o5ug5yS\uo|7-9hC +dz޿TMܢ6/,25F;ewtƆsyRU.>u&2N"ྲ 僳Wl\xM|oӧ+ޡ~0~p{mluSXP 7q7__͏f<+Y~:˿bvgYg~tV[PӘM6H!)YUK,$mb ~~ RG>w䵞 > }ۖxYx攦/&^J[E{vYk?x_`OW? r.*`*kxh7_V~"GB%[+<&ǿ1Me'EBJt?e|exzv̻?a*?]`Zk {)?ִ;探=l_B-ٶOivHpMLlupނuS۟;.K6$na3}z%z >r H5}cupZR`jǦ+\/ n_r,_Ilg-pR?֝O2]X]-#}^bƧ'eqyZ6=.^p"='n49A~/Fb>>vje/ LQnKy.,OlIRիTU!llNx̝;yrY^V0lN +%Z6O~IbC[ >8B{,:ۗ8oyR!-{_h"ÔkEk\f:}gͿm#n8սT9Wmw/Ymv֒pi'}V8m~ C~V[N>lO텓g|)}לy_?\╯w#LJ'sNlxrB_~1񁗔ypד9.ss:8]5ql?| nt*YN[tQ͊y[E6fø~Nc?wZ]1Nag Tz +HbH]ea\:'EE9Ef?Y{Wyd$|@\;?nmZylBe?$y}Ѭ]WLM;m_ +UmqY`scwD&.\BRO՗\Dz%~2ܝvʔߜy%bɑ֜wkcVbL VD-z?V3*jmr뇕m_G5ʌsp:;`w+<>ƖK>tnN9^Ӯ9&T}[r&bfF፿YմWYok̶3[w&&\]o^ +XJXZۣ#\>sŰkeZvS$TT{w$ h!*jFrՂ_Ke޽)e?c0/tlOeًu?f]ÜgpTQ7ߊܺǎk8tϨB]nƮyJτ)q{8O_bh߾c-I>{oF2;}?iZd2rVIh{fDlY"L64h—^[IxCRk_eROTkՙwV5S߾^1iP!><0;QvXs[=ϭ ܼo#WUVulSo 3s_1dm(@OP_QwǛr+شٿ&O3uZj甗b~N4+5\_XVMLMfti/۶J]щ ׻X8(uy剂asokj$ dJvPߗknxtShux__R2[fUÒަo8|N{^U9}*ݸTl.;9}![w?6M/]bSeeF~ӃfI>hmN(~W>1jì'~9]sCI3ǧZwe}f;7:ݜ f ݑfn'$gQɸܥR-־֎{&tiSivA^~UiՋK[4A32f6f3j[yw]߮Μ\*&!`τo.>Wo9-Xge\g-9irvCã2}٠%pƾC]׫DGZ.g7+Xl|tC=LD}kyb)aR`Lz,qnW%O\5jw~-y;œ8WX^K11O#nmGƯ_TFkeCيO.$riEgg g/[,:.Jyꦿ/j$3] +uv^*d:)GHFQyܿUt2|f Qs3K~ bsǥXYsk e0MYΧ"6?mU-Ұ$3a+[S J9owBy~3?yMu$3-+5l JyuEݲ^cIcu 'fs$o滃ĵU4oN<:CqڶY;Jp_,Qܼ0N-6vM]|SwokR^'y<?.~rZR*'j&nQ̻x곝HpRٚ'OY9~ 풳r +N?Ln8s#{Wy9M/0GaԇO2)(%~SD=Z g/6_Gn]eӏ^8A +ΦkXJ\Ol=Fe/Zk9m63t";D +~y-ԍaWLR]צp<OHÚ /n`/M:mnOjinn}?uZ4y;6הL͚QPȰbo|t'Unߐk=$W߂;; fxRPW#V3G8n:u)g/1&ћ+6W3x@j3y8~#A #J.gbY=gkup?iuUNw|jZ([K +ﺳɆ3u|6[4 2f-x1m[V9'=S'Mnжk[jw"9¯Y=\&gGUn\~hk52om0y1ɌI:J6fQr*5XR2˲Iq2L6/*3·q-/}Ff77v;_/_xZbnߨZWSdӊt&(I\+t( SGT–;UűYg7HRQ|ԙ/;EdD\iUx"ww +<-QsBl̷}=}jAN <8l7? 7K/u8e#󷚥̘8rO~צ,KGv֛z\g=͙YU٪OgnC_Nm+)PyqO&ku.ޠ)LK~{~3[s޽u<י~~ʔ&7kwϑU.]B%B~z%}L4og+}bk+ BTf^Z'+5fѮw:g3n{KG5ۙ,؂Dy\WqK_s{IlOˤt+(C*mykSOq}u7H+6|cvꑸ|\l'70Jخ7%}eO:?{05Fe)y\gqNcгR$CO?+^nh,e>iv_fn_~i=.ר;3jb7_(YpJSFGEo!c3ٮvi{9n'헊xw[;.)]尤g;'wzD-_nctW%sŶF2l|kK䬃G75Q$vڽv,cXZK}/t5yGyúBb#^਀~Tz^C[v0OU{i~u;.ɬزm9OIWKkϰdZvMK7/397Yh4s־_J/)+ަt[Oeګ\Me͛Vo}dÔ']5fooW#w4˭Fk f7f{nBiǮ-n6L +HTI_]X^&Бec9/o$k<^4cϖt\?'8x+lvns,ayѝM{IA +2MY0*[z], K|w\~zde׻7YWAs "5~3ŭa[KM"J|2kQ,_NCbM!&Պe_t ̾9jvsSqn‚^<2+5s,l=ߚ9?6Բ}ܶmx/)ajo3@Ak#BM;;-^l^@ĚϢ7ofYs[uי' ND4nЛ't&) E++',ԖrU{Mb!zVjO +eʖ9Q8Lyln[u^y(w +;v,-3*nxV[UBzmIOw+lh0dYԏf'?Mku{s*]:ig]6 +=uWfb\4.gyU%<]}uۇ#7}ȑyaҳ$L w|u'Yf:}n˃ wL9-eXve҄ySr2b?/YʥX1s֤8SOq~}◍Q7ueۓD3^}-%'u.RlȐ֒aՂS>kk8ќwROxxw-r[_^iSΤ]SZ\e%?;S`kۋBߛ*٢vǑQ-KYfyeO~3' K.ly٣aƫʵ{yUϫ7ߥ`ӌOS8ޭٔ]"S֥/L7kΔ2h%{8*[pg{_8rlGs@_vW{遇y(c52s>[wƩ +1ΐ]UZӆaޢ7,6^]S?nSjA*ΚcV>m+ 8A}ۥ??~v_i:6S jvj{ސ4p˃Q8VUX{츇ÓJտԣ5N*m#?\_97MօUrV=HE~ @ߦeBYWgeSs#5c)7c,wCMS{l*`jd>Vf6aK_k[m4cXgݍ N9ur+T|>&g9.Kڣ)_+f.l979{6~ K۪Z}IN_2Cl\ǤΕOrQ -Z+Xfׯ-((uG %LiDȭۼG +BDž\{ǡTnwb.+JdV1ci-K'0 ?w-yuu;Xը)>92ruk!\ 60=_]}񓽣G՘?^\5kNB[/DLZ_|Ro&x(zi&;SqO2{%Oy/>0) j/fDil}O_gz?luzkx_c̘^cޓ7^a:~|ی&#쪳+Vo ƥcهFO;l/cbgfgIK}:^q7V?zD7oż.$-y@zۉ6_Ι\;25F fzWVZ(7>^k4;LۍeWRYH6̿y|u{=sU‡Wms*q?r'Wj5߽xgV?SK%I$|teKz{ +>2yv}g8]SWάwݎWnOX4wfpyO=wcW6}NZVf> .hcԏF*\Pa]!$iҺ>n+MwZ:u=;ZZoQ%y+S։)>L}9&~ٶ"=.WNnqnN )>qbα^N=;մq5m\gͨV/N'{Cv}t2sη*iׯ ]8׵^O~6hHXdlZ!Tc[[M2]*3MӯJh?陓  +)Ye{;5Zs]9WܝxSl$J ^k޺=KԶu9pvn%">[k~zQ OѨvwU۲}9-Yv#½'g|%+ 64>ϫO)s-ZZ.=-ܶa/MP/vG߳OWm7*z5a_GݺF>nF]x}{rN[nlS͋Ħl_<;wLNlXRb9#6N +k\?n1[OJSZZ1_(/cƺRM:v\G3[>H%b~~R2o(e޵ꪷ~)y=&?zR7s Lk-?A39W֥=:uuauuvSu+6-{~hml#>ܯSl΢OfJ~|nb +𵍉XvM.|*4oWȘcˤu(ͻD oT|evM/^_qs*+㿕X>Kɇ5/F*`xHYʖ6 +GmO3N؋w n,M YŎ.1=>%_rav}{>>6(VCIzY,o Xve& ) +,8hqxg!<1>-ܿr/^ϒ{rnEb nJfאLx>ܬ5{cvJ}lے GOr׾}mniZi>vm#x{=}aJz5W&z( _JILnY(g+bU6V}qxK-cg>gٰs5ZczwY'zsaon=9WQ>YoEogg~sc"C9̿n+~>Of[gL}* Ua6ŅzLl{v15irїp_:s9S6 J)]]%sKͯ}se^?Abk/D?T}u6F$[=6ho4Ove_[^ht}w7^*qH\nFcf9߃[hNؖeQV0[;CV}^k:1I!5YYBJ4ڎk sy 1>8?bc{wUەt +8| +6+aֳ܅,Gٴ"-֯dծrz?%̪w'\{mADUU7NN}:~:Bܧldm/wkfV4%.l::{L\R>{KDՊh~U&1X'&Se'.4ڑ0#_;.~uέ՛0};O+ OJ:2Rw*QZl_7ofsU4o20(\w_WHġn:٣}ܾR;g.ͺ%8Wޕ(ڕ,&\!|f֑= +>$mW(KvF3];*qγ<>kyâfn˘K\@/Gt zey['+n]+zߎP$\8]"ѿ%VDZ4o(/y䧾6&~9%zQ戉wZ'GhT_|@TQMS^?.eԆf Wμ/-^5Ns65mq]5DN;^]ߓCSz3쳏zoZ4*RqΕѝC*RY4큪S~Vgx ⿤jfڧ^[V-VcO ]GR愲vgf{O)?-,̺Pb;&O\#8JY:rۭ"6p?ߝcrOpWZ2Kętq/oaݮ[uAjߑuIRf*#gF4լwgO󁍮HDy5Grʸ2$z=l[SO}dIO时W8ZZ#unFlW'^H~=ӧ9 Z~`ͻ΅9hxp{WBהc[jd5fBS~{^nW*,2 ޝ1hs*q[8W\Ĵ˽\_Yv'm^</p/P+w+MX|5|I".6ƒS6{p ^OwȻKzk};`ޔݡ^p=qOgD +Psxwnd0l*r 8#詔T[XdE֧wnȞǃ/9-~~:gOߺ w<+8Q>dxƻt+^Ŧ'«[\#\Y[>E +/~]~9œ9o|7W5jAUV7{^EfYczw44:YOoǘ +[g]}xIҢEQs cl:w%g2~[ydz6mW}_!<1rvi m֮(c=rV,i;giUI3 JՃ|~ylV7!teڥ?ܞ-va+{>zwwJ|;N,#=GޅU&)[%jQ_ɛ̹ϳ\,3kn̩8wKUϑ[e䁛e$I{ֻd +]gckN˿¸ؼm`:ci7bY*l4-d 5Y<r|k\z֏RW]/ų2 +_務0Y6㩕׺_"sј]s襑* {>{TCWj'Ú_#s׹6ɱɽg=\#|=f=۔3foQ{Jl +{-&x&݋o0SMڠ*'KڏzW. w?|ukd%nYMh;w7`_e6fLYFW\$˻[pO|~Ͼ {8RboԚ,xIsn}P"'u{OQ`Ors {K~Y+嬷gZ[sx9%k'$p:9&m/ (Κn)/qoSP%7|\ݢӳ^O?o,-N= f/:ڊQ#l uiSNs2Ws7{|璒.E-XLKG$=x5oPk\$e}.>p%jFÞQ2oݻ~֣יY, +{gjf]^ 3tWMpHG+_~4ڿj}rUsywS;tu%~"m?S?r] :SaT gJ}**x 2Kake-y#Uu{q5T)S֚@^ӫQؚ[S.92wʋ1m:'XnI@?֧C%|\$KQQ2bȊӿ{2]6jIv_3s+>_tޚ;>7etjoໆ&4i1:>=1q΃goi:V,8-ZXh{ў+Mzfv%z^7bkJj:TOxIķ}1U͙uRJըOw=m,}yjMJbjCwGk_Ɠ%g$zLOh {I3sW*me+_"cC՜EիCD?:Zlp%m&{> nћ1'k[:٢?j]VSLէPwJScϸmbѧ-=a]pģzg.L;ƦUtČefYteWYÃ{YUv +]_dWCU6l:J j fh͌ >ӚWf{Ŷ`̵YwuU>^Sk[.[\ao(_8sK[Ow(cPv9>U[SϲMd_KiFeigqT:-2-~Z5ړ+ʟz˳V=3B!Cj yhpK2})Jf*LvvP rLn (5Smﳯ&PqCO7Ƨ}8iyG\8/{vȬI }ɭ-3qѪu/aqKW5f;TNs̞ZbՖ/':?C8E?ĩ:JNҵ̫ +&[o3O<߰yv-Ŗ}v&bOv×.>Kn:uEiQwV5Kx!-|Or"sɵJo½mŜo_o}v,^Q s]y۾U9G//'%癄Hڋr6@6+_*.Vu{8kAR ,a?s +6>K-(_ j5D_wqe<&'y"0?NVeGRfڐ: >m7q9kҗ:+[YNʁc_ydb\f%-v:zg2 fvsv= *-]} TotK?.D3^ +jWj59_BC5K@7>V98zI07gdjZ)B;$}?Otzeɧ'Gݮ)D46m|u`~#||uOh9 5|S2A?%R/r_lo&]]ucg힢Ov;q7rskF9}ZC+?|LYu,E=U|vݾcwτ<'v1[:Q@횦ﶿ.[u"-\ЏeӋn-%KK2.śgLص3=Jp*8hBOȽ+m 0Y{`S ֓YD] bϸro͑e1Iܢ$"Ƽ kؼU* <^<8csgGn{m󴃭_?x`,g4 ~sQ8>14JF[{cɟv"pjDI'1i鎧やmZ[1]E?)d| )kX[> ;-}9O]bͧ=Y1ldiNNoRh2 Zb`IleDy"6 p̈-{k~5 /Y#wvnGS|A||#߅4*+}"2}gr5>(-XGVs̻ޏM$ܙ?ʘ_лpyV +˺M;e!Ka{oEGXxsZiEW{,"B޲()CYD3>H\Srl٥nZ/e]8#![덓t"_d%}@L/{>æ.MwtI)WH7\W}kߪvr2wl>Cۯժ/іiơW<uG'O֕q~ϗZ|vrغbQIYQ5wMs 1.H}fc~(|<(RN=>>tN,3 |UbIK*їǞ]΄6,JX9 St^wynw>1s( Ssi]_ ˉAgkםyhUǂS^S>T y[pm1kaNE=/K&tvR̈́KKB ,${&빲'p㡈.,N~qˆ?D=X̔}U X%M[bX5evgǧFݗ׬hڻ6FWj__jZ3yOl +?~\-`}p)~ЋnG/HcHkNvdbQũtjCs} YMĆ&A;˕e]^G۽'^wH(n\ф glThY:d&lVRTQ坯g2^[GsOx=ϟ9SzzƖ4GYFoo?_|rkcߵXۂ54YZssܬ f['8=3O'?A >mkF_5sŞꙨ~m[fs3/}jcrtJڽ64W3W_\:9yZucZ'Z2{Ĥ5W+d3jN˘NIDE9w[ɪ]T,luA&&qVݲ /[lI;O5Tme,(]r|+~Zm%mNG]v;u| 3[;#Ѥ5]Μ2b3[.{:NG?R>]n~9wާc+7~Py0sQaWy2;kV_J|?6$L6~ /(rMSo;[㏱קǢ+Hص>'n7^(K&3嵤Ņև44sq"A \h`r`̓GέyYXE"w^&'^fގpLzwn+gwɰX@"V߶8"_ i;䁄w}❳~JbǦa|WnnORشYR]=!}0!RMengTm-:,17g={e{<;BOF~xFo#%V).Am;;*[Rsfxat.uZT=O_Zrϥ-'O}X?u%y~}V//̻.Xus'YZ!7-%Qh|;.^((]/ڲo[7[Xf}ۄZU|o~n{8h_9TYG'6㜡wb3 t^KLB+OLŪ\Qd cĸ f/Nk=<&*XgL̩|S:$&;Yw,6ì!~^{/=ݯ'sؾ{rW=fv2]l}礅g(ԋHRc.:}׮bHU?᳻,rmS*aĢW3+n>7T<S{4cWU4Hp1^.ޕutۇia:^}V4ɟz\70v/.Ѵ0]TVgBwY;e<=UzvE3dUWwhfsv.)|UjyՔ!z4λl1* W0Zs紐l1^⟎eП':y2wkvܺq$Jda75z@גLG*\wߞ׳l.RY6~䴲65Ht6kEJj:y~n>ج\Zlg +u~A͇Ζ̙qm`k Ꭳ kO41>rd-/ELx(i;'_'csaL6\7mf;?s#RK VJ-[_]+j7j_i݆_l9A;_˦ﳒP;6DkOZZӰԚN^.βxo]~ϗΈۈ6H(XĘ?v~{n;/R<<3[;m}WOMaN&}gϸ򋽩[)/|+Ƕ⊕D[|''Iۯys_Q|zmQn>|T6cYVzқnx9KcM* esf^d3l%̖N6е֌ Z=O[1Ȝsrdæ.=?#'ܨdRȕT|l#N/-yezc?kndXlb_HvIW?B8ui3`]L{q&]Ko ΫU_),+p= Hń^Zx-E ;T˗NN x^unj6_:Acf͔ 9P{pϏG Z"3'ɲۛ/Cl +%n+0mϊ)go_Zdŝ#g;zf޷ 7S0|u7y=m~}BXø&Ͼnss}高/y8:R1|U}ɫ%^I%k~f?7xM6͎}t=]ukխs엇g\,U4Qd?s +U+wB]䚳v圲'l+ ˗/٩~YÜ.:[3TM}[>&ӫ,G&d7W։5K_(l-t@6ׁ>T0H3ݥ+$Ν9ΉPxu4o߲ frpscoct'NJ^]x6_6JhpOkw+yخ9?ijnemv6?.ݍ'I}ܿF&ְRElR+(;'ͧqG,.j{χJ{ۧxga7L72IW^f7[:糸X;GVYZ%[ٛcKuGF5v_S{qe9UMȜh´2kη`*g +[pWؘ݃ϮvT⎅e=f|3ҩG˧l yꥥgmMYw|7g2GSv~씕^[>iv^o /#w濩:lH۝|ߖ RK1эزg?rKt&glu;'Gh MgX˧_:guTo Δߝ;-)_Su6-eq5 3f'\O|ʌr#eWfW'2z+APJ/9?H+YWѲ~wbC¤>AL~~`% <* q*hA2z+禺fjgߊ]\#l&#Rqo'tU9]ߦ5GMӂRo0lIMqz&+?gf\o[/Y9c 'Ӯ [vl}A}q^(bse`п*m3.vY&/9w=)W4'Ma{6)5/9^`,+l#&\fo|8'y{ 2+7mV߰pd|zW\f h})7w [Ŕ|{kgQTOzXw>=19Quή;uzDZ_'qs޿U;M½:x^wX^"7St3:ؘyUtA\sձ?tyEcsNèhŽE7wƾt`oGXҊ|y?k348֧UL&LlV {S~~ +XIjN=/ex7ޒ0j*혧xbBo׾~+V쉛6E<z2,&vd3'ʲJv_[4wYUЧW4Už(}.1{N3ܱ_J0:-X?k8 o}枣V^q t3v4VzvU"w޵=0#̜ԝ؃V )U6_X[yx9Tvksl~=vYG^} ue냿/jgY}cL,R~tIJkML +ϟ[Z/g5MEb*k҆= -me/g;WxKvqt|o +oM )e',8yvȸ_\Jwc_WxZξ/Zo8dͫ6*Ƶaw-z.9N{p񐚱x_7SQ^)'WyGYfŬӓ-_=kc)?uzV]uq3Y+&we_ K_]#תm^T9NktZ+{﩮IU2o\x O_zoMYlq_ܼ/";b}ؽQN0xמ>ydީ nep|YS|d7ɲ眞~xo88}Vjx:?s'QZWΖ<\ЅZõB7Z8q1G\͙%}S6.L?;ꉐ>+N4]5p:ձ w@]]돳×3wũi,-\#n=>o2I֍4,_~Yu|ܯWU,*2ޛHmwRFIۗe&^p#[0DajL\g&mȞ2uCkgVmQxj[o_|G$/YZt؁>; Ɏa$7q%d}6wʺLyI7˞|{/ y%^mg[O.>q)Օ_~+o=Ek[p&45Zw)|ji;]q_`AjG˩O.iXkϝuq=>9_;`ozI ` )]RtN:'Tҝ.TwST#o;{u_vb%"KRm-~|u7ޤٳ$mOB3ߥZ[˜p^Wne¶j"Oբ {WR *5b;ls&qA/fj,mx$6}̋dh9}Ur5>d#~[{ :mݙs3o_m,jv]&}p=gOX~%.rʬ%p%u]长}nUggm=;̓9V-ݐ}XMuΕ׫~lٸf2"ܝ/se]i|/,_IKi$xmgg3ш^ڲ8r̾},ƚ^vP +'9JsV"eUe%ҡľ;?bݗ˨xƷ/n?z[Lcf\靼a7ks#.u6ǫ}2/W㺗SYE^&2<?nCR&/M[^;MQSp%}7uKQGTY{MĘf=Ytnhc_ 7Oͭf4Z-?5q%"M['8v?9wÌ My~ _$n727DW8}Xi`Z3_- ySe^8l5n[86,U'mZ633ϯ~鬫=~;}{4or۶~YVr;C-E삁~οL2{u{\n~QpUsn. kpvKP6m9W/SdJHXؒS'eطmRdjEDMbu|3`]^Wf.v#18Sy%m}.6t6ק]}xt#;|VUׅͼ"l?Qzw}L:N>WVũ3K]Hk^e[U  cﰭfQ~rQRoKú kfnޕF,tXթ8',Ys4&ÒI[w҂m.oNMۏyG~ʞ =Ӹk')F ,Uم7[{mKҌ X>6_Jo?-w񎞕zKwo%M]-Vob:)q^9Zyu ּ^Qnr<ֳw^ʠ,{MvL7oO, Z9&E%K?0+LBo\<嬬P3iqmTY_~SuSW),~,J5B7;.?/laSZ>}(/E9̻ς"wW\i&2ᙦ4[,_}(U,nL3ݸ\b3I}GMtrZ,% f}:hXEXĥKi|ag]/[,o˚6>h+F^|1GZJjiڽה^s=Dǫ_%Y{tַ؎}=rҢUW gUwշU E%zp9 {ENOr=kۦ YW"P1ɧK&NlNɼ+pJ&^QUg;1k{wK/R՜R)Ԗgo;Eq{H!I+]qH+"aW?cxϲ?fM:pljºN>˸XƳt͌ӂsf([btw.Kӓ{W6rITk2{s;,p,ӒcϿ](=c7* no)+se؃]K22XL]DOڠ,U3ďٿsdoH:_ygVFioXR퐌ao*_)tGOK'˿=wluM霸{O&!wwTFeY|H*Ckx=r+dXo9wޣ㾩ں?o(-6j;(_鞾E#7|R8wԅ=2~^%J.UzOm…z]u%ЋfxMzWxڽ)_i-6S[?fWN'|9܅Q$5夳A3^n ٲ,f2>S3S}о#x=ۏKN~ݰm~Yg37l.ݗ2Jq$+z͟:n} 9KD?[eɋ͚ee峳OTPW2 X2j=W{[W<{QK)75}E%-/pp^{?r/$u_m9rOJN{g]'{HlƇߓoz-͕h'R*_jy8{N^W2;Wo\ĖY-{s׆kA29woɍg*~jwr>}wW"گ9zbO0籙Z6a˅%31|zF e>92[l9f_-}x풥N.U]"O <k0V5RL_͵\Ҩ56Y#G޻,uPzK; 9 *Jz\Fow626g U6."rGWݔc5[oMHߟF<ڭrOV^aV fmb˝*4l1ʴ+ľu ss)aU':"w݋oս턨}{Kn]t)֏tD0p/ۧwJoݛAkN/+w#ٵU!TȲ`sn?R߳uwk]w3ifлJxĩ#MeB_YwOеu(u_g*5c /O&o^Ǖ%̇_gy E۷/nQcs^<\纺Ċ{[Ο{l5 ?m.6uv] sֺoe`pG )vŐ0ՇFV~μe,Pn:! +/`Yu>>Yy&b6rC݇_r;.L6]g T2d-:ӓ}q&.FW#xW\8uA5|G'o>[ӶFXx{Ŗw/\bcA[]OHũLUe셾)׎y$3S,W JI{ +\fL_;F0YՋ$cgVxuOm'{^лemt*)[w󢿎ˤ=X}V΅G4|r$*ǜO# Wؤߪщ +KΝ.ș}Eunm1 +g.? 2)cކlY]OlVEh'Eaݚ-rS5N9jyQOe+4tN{ԒfٷKnH-⽐N|Ru'Ξ<9uFYK+Zķ9n q;/'Ti}v-@nό|9oK0Z#Urk>g˓<.qnztd 8U05{7'~_5ץC6 }~sµ?*VE'42% p:)Lq{\Lj<F9$bu^ӾG?ۿ=ʬO}.=|w$N֕0_̼_7HFsNɞаܰ|V{96gOZܴ{CI;/$~xʋ +8ߖן0U֣dr^84olR& ]t潆ǖTJlxNy~a57`'50mR&EY[Rmpbܵ={O8׹zCUSp8|c\Ҋ{.8\9iܚ[Ǟ^QXtKJf/M.󶶶I 4le21:xP o0uS33?Mjt6}rwz,7D!} +$_p 취vSۗwyeWKz>,ֆGbaa kY f/6N->c!jߊ( N so ++d:. \9&H}yu;?2R%&*=63}jAk_SE9dL?yxۭ8jO/ fVXz󋕠FU,4, e5UR}~۠Wjfi_vٻ_<)/[%u2r?۶z=)[^+jXO]}|8܂W8qI5lS/D(>ia$׬/,15GNY_n{a×=ci/[Ւ!6>Zysk+˴"lzj;w*>Mg%LhEya;W^RQ.% kwl jBRgO3jmuGD_&w`k=d^~\o!p,FnS6h\4k{pqƓ)>7qA/6pyl?'a]{viȟ]ҾJHpר,gõ}2"pGe#7N<OCrŨdulcǗoc$}E&\櫼{Dj4]5w$ѭ6,yWz{G-6!2L>h2#H Lö 2w4~X3,aj{´(5V/?7Q@ڊD:[e!4JS(?lBEQw pߛt]')mnj9υ+VUٿxLީ{=ƪ/rfM.Wv?z7~[u Ⴣ ye|vݱ _zi7Su/ _ߎWo&pj1Ѿ!gF/LmӢ|qoŅ|?355*o7ťdpzW?>ӐtsòOVO\+,ao;KkXt 9&D³]tΒ͎vpr #kNZWտ~;pt3ʓsjV0EIKEqJ+E*/V>8GTx>.|ys}m&4ТF?y9[Oi6`NtՄDA|JaqELZīͻ)}RoAa śD?GҪe +7oryWs e%:9CF-(v]s{W'(3uoGW>03ozmZO Yy-~Es20_*}a;Cġ+4Oz2ƯȌŅY+kWxv8߼vV-.ٔV蕓ͻkç:K.WQbٱv{NэsK?ݾJ ف*Wmf-st\_s*uж苷YN<ĝ7[Ѵ]4k_,fa=6Oyg=R+;37>J+e;'s.7'K͞~[>XO>lBΔOuoݻg +6m9FY;ݣ41I5/޸]yCa Ol xxApA})vKVyuij{מk6GV 8D\ףcX>8jœA :oJg3_]cyQDlœ9g$@E{5cOtiw~+ mIKZxen+  0Y"^ʼn*e3-|_`f{6휶yMRoS-TaWۡͿ~utu_8j*r$*ӛ2N)Xk_eiG_7ݼ-1}VJc'gDz&V\IKTs3\2tH@wYugzYtetȭʛ$ݿg.ϰ2?zfiqݳtNA ۜzޥR/l]>-eS3K4ϷE57VxQʷL/ϝb~tيҶn8gM!-[^>[rY3v J/8x?X_k^x~Xؼvrk6a٘Xoׅq=B\L|; $oH:5IdϛK۝vh|NMA`s׵qL5Kc{SO{_}סBVtika<oZbxԕ؟m|ԿvǞ:|x[|ΦWyrI‹=lܙ׻뗏6|709eaƈ}Nއg-О{Av?=pMⶅեu[4iizZϙl[sn2;Y-ޔY5p%_tn_1X$ŨiN1f<00Jg}N21f>#͵1NGX52 +i,=ѣ2aS^[6rl/wq}L} ~V~{.)^Hxf1%7Kg#TؠuAi"v6yOZ7?r(΄7,g N?E2_ ty'XUVe"쾱ĩ jo YB_MCfGKY~} /LM_8/t=\-yUtm]ytlwTG&K7K]bl))x?ÕI/Vp\ײs{~a.c>%{~\Y_?Eߏ]3y,a[p:ɉņo[veҊ59fK5cƩ?H7[ {2;w~_V`fm~]SlKJ>\wbFy杋R뮘yKg,7(Oo[o-Vo ϙ2̾z}3w[%٦חyZ{^(M؂ʳ4WW93Yj}͹x㱳RƶϦLHm& rEr:]kɎ*Mb_9[OZ+%&mU'?|7&L5w7֪p*?d&yHZɶ}16GJ>.ǟMQɬdUm U;RO|_ߘL9nHûb ܓe]rnz]8i~"{D j8f[m9d9M,̿ճ릯;vpBϺ#,'ʘ}2U 漬V\Ò|Flx &[Nqdųdl;{ci׿3:ekc8/9I]Z&ϺvI'6kѧ˯V .^^%Q?s/`K㞶2V57'^bw[̑ے62|wM5-'غiҪbYtĻJQdvɁZ>JзBm_~ I~^fd_o"Pv;aژ:Y)7P;cî<V%5{=ꛍpˏ+<-´j O9pnn}xNg)$i9203k1Ͷ>w䵅= ft"fUpYՌݏX%8]TcY&%%TZ\CnFT"Zv-m/kڜ%jܑOU=ވ'{|[U?NPbM,黼R6dբ'Ley9k52cr0!> {\.?=v/ŧ7ĮyjbBFA˷UYj}w%<|t/KY_ƻsr.g8Xƣ_G[4Jlxєݝl-,>CJ/tu[7{[gW}}3H8o)yN]S 6e9M;{)\;ߜG|cmUaZ)y߆]hwR` VųWE)8hGlv鄠oO۔PaiqE|~ٻd>]kgMM[Sog􇷏:qd k֟ڔ:x/->۽oQI9;~Nʻ3.1`ռf*֗lv0cs-5M,xr;YV;%2Z%o6[~b7i{r2%!=rBM,+ +很tQf\>Ԥ{?C+84+RF~Y;~|~کm;,bv'.Z{ږasN2LPcrx,pPg}{ (PcicVN%TVhެ{]ߎ'nuNJG,gŇ$x㋟ -5ov:6iox͞m\N{׍Tsə7HZV>cJ9|5mmu+-l:Y^g62WL0O#۲NmUާ{{݂@%?9Xbc_u}-y?'|p7wuL΃+c~^h>2{oDȮ,Vi&+WazQɎ/8{x͔{5ZpS޹EtOڥ7x-5UQ\1f7rﱾP6EyM[oB@ԃ˿͋4sUaŞ?) ̏P~7r(94)$#ə^rYuf^%#'}"?\tpAϭ+Y,9p{WNYu!/|tޒ/lp0 :Tvov{gg +Oʷ+˼uor9(w!zIWLIfUӓk|.uzTUk{mr$a/n5~c&DsںnvoS:Rf^BSeF UI'ʻGu^X2,mhm=T>&uE HT$n-Pu, A?~^3޻M,O3Myͽ>FĮ-n>7 O*ӭNaZ|c-'dY ?ʎ7s۾/̦#XTv_kr1Ըa}*}lsa$xp*̯Qa{eULNt}"S Z,RzA%Pׅdb!U5՜LolBI|vԏޟu|_&;UlguNvN !ޫɾTŗ3L>LcO?(+zQ2#)=O3'dn]mMz9e'PjؘQpbu|ti k<1Z~ey6俙k[tඅz,A(5]{V/11 hn~5I:kݙ!M귧9|A EY/j6|@?өp⠲iߍU=r' q+ng7y4KL.etAô#;5b{/Ix㇤l?Ykc*Vٶe?ŭt.DC&HqMKkOcJ˙Q2`EW`mgzV9yb>uK?\M*㗂nlPG>;'R=_SxzqEˋW]i {8i9k^c+WTM4x3C{OwZ) Oӵ{jޱ>Pg%N/?LI4XǗ}wzf Kw(ߡC2Nץs7V*|T7XÕӘ2W,s&'>,2)ts']yf=}]U/LaX$/?.=`V!Vo>~m`G*A3߶l:I2/pO'|xuL+wI̺X%;?;s%WexKEN[ʜnO^{l+Ogsb; + 4B@G?FM\m.ۮk=ږHpH9 +ǚ?"OV2a a[:˺<}ttݢ]};jdV[XC6ǧ3++:׾2ӯ^5WfT+T,}#+Ew 2>yP qz|!^씿=ߌ-֖'| iɆ|x<:(x֧ϯeLbe]kё߻J歓X\,9:%Tye랩A6f2;k}.NaQOYUʫ7|ݎ~O/-l 6e=,6<¨4dC٥K>/Vhq +q{>Q(lj ypc̅g+:%qr_dzCM?CV#⽇2ȓ˓:m0Q`7]%[{V˹DKHdZN_zӄυb?wo\akvGi/;d^|7Zq_7&DVwUYù4zId"[z~b]lۓM6,2Nz{ro^m]%ƈm+RK-m7_3)i/gD;:U_?mzU^;i_|Zթo=;j|LS-*zEk}7$4Gt՗87L}_@{Vj̊}2rgvlQ*"k7*Ftun|4]C#2ʖj{y^&=L HF!kE9I?)F>DI'3]g͝(0GdGҩGnVĞrr7Vθ\!On˓^~)nmRLqpͽ—-2JdJr۰=J3fjt9y~~ K9jNVfq%Ͽ`ük_MVlsf|PXwϧ]rxˤ5nD7^>ݗ/2iWq4y7?g{gTWfo4*\11_4"7c :+M ṕtCmn~rȹ%&J[_Ƀwڋnthp{&똦1g)˃5}~sB*ӻ>XSz8kقwVZsn#,ހ=z?1-|}~F^…Yw s/HhS.m=e\qݥvYǀKs,|wٕ~b9W;;ǨtHE*>~9kEZj񳮎y.XY(29*z~,&ݯkos˖\z|ێz;BhmK~v߫1 +A[Z۟Wn[{-}6?igv~[&޺JByM\sR;_4K/bvoWİZʚQ~>†ink+.l0f{]sUKAK-5͋ܲk u7+&I7>횝_=SNq +a^\|m%ulgkz{{fU(]&'j%:kg S/#펳?%-eX;{2X{Zc;G\aSz{%'T?^;pmSf/\(&|:W87I{+C[ԁKk/6kn~"qV/lQ3*?|ZU֚]n5sX*|uq"1/M =3#v'!\v,/XN3W7ֻ̻)Mǯ^ןs? CSBWRn,}q.Դ-R2;%-2Om˟G.p׹RA+_H:q_'zU}n?1*Ok +/. \iآ2];mp>'L!/oR6tCmߋJgg]>=aK.746LHm{f;q5Ot4K}YyHosTת7[^N,L%~hu\,Z*ή?9!҉xYY{Bʭ֋(lK#aueϏ.8{uЅSkjO߶euй*7-95}Ӳ}+_T=?VN,mm_`Qrۑ*{>Jȯdx2!0w_;0[eSf?mwb,$!_$lۢࣉpI{$o=s5B58R|F3עJr/ɮfL<*ߝ+k6~|H?7]e֒ǙYWJ.\72:}9:{5?Ϭ}yoXڮwv.'+ZO[__ O&8MCS~uw%x-_o5 d̮6V{s#=Łʦy-yz|2#f/8~-2C|rGJOȞB]Ҏ+QfO^bDÞ+"x7L?˩؟M'U=[1=k_:Bz>i7W:"6}+ ;_[Ӷf/i ?^V"vȩf{?n{ߗW)l5o}>MtQ!e6⊍:t(E]d:o{͵uƫ>ǷIyDф%mw۳ۭlYƩb'DNMx`?X}gK49J__?<Ծ>۞O +^__`s6Ӷ]J".j#VmGb=?HLE9M-m^&%8啋ӎX~˜.3_}Ф#y捎i{ghlu.B.ǜ_v(4fwщg~4I~=ӿw=?2\n[5%Jkvׯ W`Z[cr 3'1ak)]rŵA 72k䛰Y6]gGyxӿD=Xz)gv18'+{.R.OF|-#yxD w>iywO=[=R>tuA/fW5ݙwIPmz;ئwG.:eNnf1r/oHkJ7`Ѫ e*X+K< S'q>vc5~ݚoYk|3=heQ5^~‡{vzO%8zL# +Cyy1鲭JUZCXu򱚨\O|[1GZv'}S[*BOclyU_O鵸ɽ^*]Kٵ/ mrRcqeBknmO9\2M9-wkm|I̡~Yꥍ+*8c*w/ +~P-`zOE"%-{Udx Osxnž +}Mz¤tx?۬zN^ϋn/[g68aM2]z$LUdkMe嫓BvXYv[ݛd]ZTULYa F]?/V@^I=n3*Mlk"lQc+ ϫ;xA;ovr﬍kiE. M:FzZ㷨9k*_4Z4f/3hxƮϑ7Yx򣹮$aI97qX)&'Soeg7Kٰy EJ+W$ا.}"rMYM߽R`B؇j f]pK̝xJUӯ ^SIsdϛ}*iW\f,g.z5ė-(YXH3j [\֥˱J}UJUJU݌R"$F/Oœt@hY5TywZnOw͛_frP_̛ <۔o[~ܼ5mE˜n^S9Y*(Ƶx~36q-Ql#X}m]^)аmirvu:]W~ċVL6 1_8gyG>[kY1:?WݸchyTXicyX0V6K.aZ s"% 1t˾~{yh>忔K$.w>_QGֵW>7\5;y^3'O(2}_xuF,:bBk>,7w#v*VVrE>2Z?4@]ìKDۙY;޸L5I;?˝^5`󢥓{bND {FRڶ6T֯ 3zom:u==r|%{La}o) ?,:0oW\G⑕RSi>a'gmq0CvY}x~91-I(YV{nݯI=(S}*ɲS3q mj\(̙{-֋Ǘ[r|UDB_|kqqɂ  +33eF*>^ͼ\oOa$\׃g||_uqZ_?5o4[<9K=XVsim\fHte7jRkT?Ή},,osa}}O=Lϻ\欌f#Es|5>C!n +k8Ŏ[ SaJS-뺽#QŸ2ĽL4&JOm*"gdz^+?_o3]}W%pStj +tIWT>7fjgd\Zާ_{ϟrjo2rR)t*x0V;{ }-$w]98"?cA;?Rlޛ˨s۟7FN2"{Gg\ܭ0'Fuʤ?NV X O}9n`ęYh}|˙9[wqr?5u[ܾe +".X1vz;ܩ_p1QkEumZ;Q°kaY)jU.sŌ`ǒ[lړox\ȟx999!ڪNRx}s&qG)r.{Vh^\^1!Eb-I^>7uKN%r忷YI i/Vqzn۞s;-8#׾ǓX,g);.z&V0ۥ&M4Y%P3g~޽{x.2`۱t>Úow;-9\Qf· &V% ,d*9a| pr֌3޽v7)S~Gɵ||st_E\!75<4#e/?JΦ󞚹dNV׆a>盞8d#fbANjF&sO2p`1SN/Zs.C#%+ +n{z!{R3M}WǛ2'ko7eq?=~Y>OG,1j]QN J+ +xuhF25&/tW/.n>8WrQގ`7,$lݧ+n9}U^6ݒ1k8W]S/"@Ho [vO{%N'8;B;Vn|۳f߯=0냌 0(y̕ BKW_0Ӯk>މs4eI pרQOto}jB/xYfzތܚwvX{dQޯ+G-N1N4z9hz6G̽ %z_+*~F9*s6]hIS?YrH.]{v N|X0 ou7˾\F0?Qoߦۮ,m/\vn:a3eӹ2w|5}ҵmmý956i/Z }&{ͳ̶bO+ժr&,Ͻ3fz|cBϥj$DE'R1bvϞQsn ~eϥ+/rkImsVϛ7EdME<:ڦb6?^-CA;*ూsfrP?qo׷]tsXObW[>nai64y{݆fU=y* 6}*Vy_`ǻLy+- yPtgsR{nX &/kwxtў1Rog'X=+~Njgz'vqYuZL8Ҧq Zf9۸}3͞\4;u#니jk]MXL^YfeD˧8nsSPsb'&]8 +ˁ-eZxV')Mzg3*q޶LAZӼMMO(a9x[C~{C$r7 +\9pߴvܴ^>Tpk]+o|֎V ^=N8K扞k+^h>3nf_wF噧?}:^vi  pyʇO=Aԍy> -Ռ0w\!{Mg>}:]gVmm'糖/)4s8}7n6rԔҞ;={x}LY.`3cO'?/8A#pt}\a>^C){ _}.;-+o9:}X\ִ.\٧.?.auc3_{ceɓ3lx7*Ӗ ZmT;VTq?kb#LZVu(}3Z kkeVh*MoZ3w"Nu}QVtٰ {ԶEf,V <\;•Yi^p'L菅֖ƾ&zrC_n7ITb s]qٮzw(28LKƶ9ґ Cn;(Xٝΰ>Bf~\TŵFS_l3 +;n6P},i;獭I{խ-z5/ݟ|X}Ä:X}R8#W˲J\1l8Yso=h4^gsIo9v r\'c_u{nLf%&DwcEJ7+mv*I[msf u_?Lwޔ!ղz$M{g-Ϝ^`=a}׍[^vrO$?;3Ǐg},c3|1^:j<$6mM+9h.V2$PՊ_w2+l36 _\ߙ[Xv%;rTm:.Lu9 ""t]Pkyr%5z&}=?̓wm]ґ岈C[I*9R6,2Ya4uyH?fXi]_0s -l+ ]mt4uݽZZꯗ[B[Kc(tvUt_ZژQU﯂Skwy}z]]"V_MVy9߾jsfc_FI2Fj̥=J,'+lM^Xh|˷~R9X*nSڱ0J>Z?&˱vh\L[vK3;(NΆB}WDnlۏBrXi_p3+)G*[Sdo*K8VwêK*8N`w7±:= ڞj$i ?s&,q+x,t("gƧZturÕ̩yaΘo^{?3#_J& lIR5's=/tOVbr|CEقrr?<ԣ9uw~`vxN{KfΑd%g?uia}?GJ UBl$*mӉGwζY0'E+7{nw_7wAdOa7{6by۪=]Ԗ0}<,}TYKI;?ҾRx4?e3`gtN*/%X=ܞթl>k.n }scGeݛuAֵsޮm_rfӇ}?L8yFh-PU]ZFPK[u,|/>}{A†=V3}yuDM^I>q^@y&3wT!p>=PCǜw=}kP25S_~21,\yܯs8{N `musRv\Be8+[qQG` U&5=Db.30*k/8XSz?Q^sFqZvWr4 v߉`tZ)soKE=~ͮTq7.~FsXƵU{b{ث# n}ux~si\鶞SN +'\,8?jxE0dز}^JvfzqHeݷ57m?ڝ^#fg35ys[wbCSfjtӌ<Yp֭%>UR>Ny|w+csEN|.|YG>|chAV=PNٝ΀|vLfTQ?45;V2Y h`v?Pi[܏S461PTyJ=ƜAb/\~fZb1q}~qss8{ܰԒo11-t%Raswi'Qxo-bIk-y[+!aXse‡? =L~ė n7mҲ7$FWƾ,#E9W[&^pYil 9 17B,옹KeΪoo2afs37[ưPu5a +_y[FFpR3+Nuɟ^JWfeYv3*{{zjb?2JWI(-_~^"Z۳OWҖu +vѥKgn^dIBS=_/J WI,{uߋ]+߈:Rt\9sacӝ}gN~S}JMuV-vat.eUߺJ h^ғH\ZU2D;.{0*$iU3884>9~A-?kg4qrgq_|x)sS9]%qI'~/Vp;`Wϟ|+<{u-{K+xmϩGl~SY]Vk+0ef>B+T6~} G6=JW63~&oW-^3d]K: t1)oTvGMoy~K-ݎ{VZ4 ?ub?h~߽v?o]/8̢{?]ttbsE_ +U0νn2w!њ )ǥϙ^p>]ѵo/[qw^pB>+,7hCO(wg-#W*/!tyy)c>3?z;|=7Kݴ/G_k=>^|yޖt3 +i+p%u%/W +{:N|/KOs;렰ҍSo\}{oz\Z?fv&q^$G?.!9"x0Vmӷ:fpy.e'u&d6 *Ν-6쪍eY>axf齦WWXǥ睚-9.d]FX G>~\ܧN]Ը礹~R+8/*].[~qM幦Ӗ6۽5G_ߛ7g׿0XwAɱ7_;o28ۇg_uzp߷:sŤ}{?^\w qaDSoQwn\K oe:w_}-ό5)2vN>ꇙuS2nwa֋o+yZvma.~x'k$:߲jw .:v!3k5- 5wm|Z5A)z휲 OJ!& ݎZ3?%ɪ-M'Kv.xj(e&vjnem4έ=K?8qsՙ! <\>4/nVRL~R!8o^d&cy/Hod/cvy.~Zu.4f|Ц;grb./\Rհw N#OPoN7kh{qcYE;Qg[͝6֯'dwS3Wt*:¸=ovRӍO*!)N![˻j!^酅,E*>ZP_GSMo;#egq5Wn^6_|ME>޳)X=QwyFQ._`eW!vBUK셡]mǿXw?as gczaCy~ʹ_[~N +\x|\ud>}]]NUM_:&[6'']D+}` +ߨgx2U-g}PCi^ ڥ~ᯢ><3 +}io}/^<86tƋG>-ӝ>|yMu^NNtI?EZy.e>~>qEB~t¶Fo+%q@YuB):emʖ-=ͽ(f mzљ{ZX2My+D[ )F[ >pRg'ҟm23EIv]br|\wKWg_>K-i-VxbI(}|D\qsE;f[VMs.M}6Eَqێ%~Z㯱nyr{0i^;֗gՌN0cYI<+6l#k))AmV`jQc[{ݺ!o.yMvL։RҾK޺[ϳ57nD c\È%]fO%B&OG̷ޒ&b0Tq}1%ep@6;܏8Wmi߄)5F;;%3Gt^o\ɜ야׊ٷrlڪi%1|JeaPm;{cVG>{ȧ̳o^/]կ:[_XJwC=k,3z"k{~͗cY G:9)VjNbן.^3kRC7owCTs[w}k~N|W8}:/'S^߷B g%t=νzO?d<}#=%?E@ԱwlI 8d'̸VDž^adFke|-ys)Uͮ.{WȾ>8d5LI=t!)+Qӟܶ`w%y6Fig(c)gұw׳;+;smy]jMu9Ϧ<G#D,󳗸ٻ)qNSSoM3~&M)hS&ޜ{C疪tRiVY]g[$]8~nºsB78[a1(4ȮdFgZ-9T>*M-7;lDm5ug0k_LvZ;-MT9MHEw?c gl6Nx}uQ1˞%sW7ܥ[7eR_ՠ9;Y"{@uKYx89'?,8hLmۉw +>"Ycqpն7w5?2oZCl]ܛo37JslJ֛OlGҶ^Trxz={%Kq1̘ҤJ]w`O$ħ~HgEܵs,_~lfoAѶ}&>mj^8slC 5o3oL/V椟IVs< +Z3Vϴ=kf6w-9qkݣf^mE /e:NOPxBLs~?6Ic֟oyXn\[t]ZbWuS6^_K$S Vl`,|<ӽ^snꩼ654=_++.~%bdNvO;L댷5'StDЗJoeoFe޳7Ɏy巏.\y'6<)9h;Aac }`yex]7{m5͖ )^t9%8aC~XIw/jhtM~NB鳰Vgu:;ǐ~8/Nu6iw,\fU$c]8s g w|ELUr Ku^sbNfV0.u/]WrV5y+Z;E5[&{3G[_3W^NgC0]%=H+L-[:TŪ>PWbE* +1?!xѺ̼&_:u̽2⺿Z.~3GM[녲]9 o~nXU{AO_ +eqlzZ?uzIm?0]ZlpBuK٣[g-p߰▩4~uo?ں˂&jXa_7jjި؋?tT1_«p1^НѲ}?-z$2UL_YzYЊ{$%\2zI H8 d}(EZg#sV+29ٜQvρ Nٻn9*Q^i*ή3WoON3(rƺODocNr5 +*Nf8'm}b@%/ǯ|h}u^.}>?w>d𚟥ϗ3\mTmׄE75\WZ2Ch7\b*]+Q6_lrSI_s۔zi5M=O5e^V\F9]Sr8Ĭ[:/;ƈ'ٙON`Դqu o +bqrх|Ov~ow}Y5`0M8/`݆K3ec_0i_TY`IiGsH6qnEśT TM.7Μd̐9,fIq5fE[>u첿m;{ebLG3/8_1s,پG=nInٞSe_1?zM{9wzAf55ϭNwe=p&mjX}}En6k|QuŃ?JHe+{g_<.F'l +oVdUvۉ>pETaxrD 3 +m| ?WkLe&[C6'T>?:wkw(t008'twÙ['gy7LCM54js|i$AEYvܜXF^r߆/l (q ̤g}<ػQ,T\j*էf4a;yj9)_&__&Ip[(ӛKK|STM+NRko0RrbM/;y.ۢ?ΪV;>aZ^RцG7yS/EâfR ջ/XZS1GD[YtsFlk;M6-?䮲`}E܊&k/DuN]\G{hȭ{~M3:$|JX>Hlc|G7T]YOl|3At%gۧoN<mz@IL=O}޲)vrBu~ޱg'm[njlq +Jۇ#~;VV~܇.=޾U[4f%<*ti/ղL܋zQlbxg\s]5k2sE/܉YYUNJ+GoCv/|qνƇgqy$m%x/1Y>u+V~j}?W 8;_K~uon^WaQ_(e#cKf?xbowU>V {'rWޘeU6 5Ny,tNֳώ]rc~k̵̻'6(90//ݾ>V<Йpr쐰ǯ$ n{}gUK=fvߚ;>p\^mtAusѤ <-/r3`}{~S{0"!{;˃AmFJ_>~!m2==Z+!-Yײw|fDq)ϑA"|O" +ܪ|)bF'rT=>5:FX=(n37>59cE#BTѳ|}?mR:K?1JXBy) &L]W:eH=+^oyMt{y}^9mق{}r82{lOk=CR~yoΞp`}3lzjoN>}uzmOt-UU~!ܟe5d{Xz=Mx(v(ҦRcDŽK]g*3wY\V"Q&u3 l/WvVjьůWzuNj̃,ܸ-oep[Qa9rqu_;da?&]~l'g+y}e97Sӌ GSɛQI \Vuo]mwi^6ѻfǃ%Zƻz[+X/k9%CsC։ߵ?No?YJG(ٲ~׵Ŵ?pAo\e~ʭcϫxy8ohZkYPޟ/Z&eJӺpBf^^6B?_ȔyR#%eb'~d7iv/_#lף濖;6hd~{x&5 u7:qo,b+s7hk;]cC7170K\=IYwjVY#j3Jjp&hwr]}ե x y啶 }ݳ1Jɗ,}բw)Un/d0;sQaX=4ޛ'NK8Lf631vhgA Yϋz[gj,_N3}F͖[>ݻz!IwC {zpL[Y.qK__5pwӵ6gi] i9f[ٱ3eZ\~A+_[FЄ}7om|]/Z^V\zJWUӊ& gel{'OD ={6ͱcP40e3~-,9R5=%}k *4cnf 9_pݠ7ks{xcwAIqO1G5g,:k4J'kӤ*U܂0(__ Zp>v ЋR}\Vq۵섬kM%_tz4Up=h5=eL]gU[3 -|6+|S;%W?tz燥]=nBҽ)OpSc\֧]=vѵh֨_?ːŴ0Z S+X4~uH@;3|dxyeSw {9Gߴqqu+.vVev +?#YgUP݉ +ƌUNVLٓNq`ᗨ䆒97'-\+Q>e۬?? ڵNqƿ;%o^ϟYW岮yL ^/zm5w}编7X>F[*)OdCۃr^w-svOr)iyb^iwwZ|=d5;ݯCZ{qk'7M}-:;kUjrEu ߵZU9vjLKsԷ/n$#9[+I8Zmy\ %O*ܒuiөܾPy^.0F(&LbݬO߽\?ą yr}$_^ڬo9b"x]կ̫b6W}W(2vE +?]|YLTI{?c'2XTpQΩ.<xv1M=jPKh +Ia~GLnl .:D+yw>]9xmM<#_}i؝N)sy=׿}g5~ћ:+Z̭O8T1uJGYD)jQ ėv?7|t>c)sUԋ99?LC"m^[/?8|~i宩]vzw{& z_qq+U"3/މQa?21\n+IveMm~!W,iĂ/d9UI^>`z U.o\Ui[E?O,ꪉ3zmZ"Gӻt^usD~9‰+z/_4]gYnqnjy6rozM,xfoS3Ԡ8~[ +!ݕQ3&˘{f7f,SY75ز`š߳s'L8rY]M O?:YI׿0SzRJ^zi3Cx^YI5z0 +yl(mhˮ*VrjW{hBwWOM,/g1)4sWˍڰ=_IM\Ɛ[KZOjюs7=@E片L/ҒjyZӌXԏ>yZ 藻]oLd-~ۏI~8qA' +x/?9M#J +_//ȟ4(wn<)m.{Ue\ߢ16j6 ow.4{Y~T$Ϯr+{c`;tY{ԁֶj٭ +'_i3o'm_,U/Q&_VK^֓l+^M:4mgdukd{0n>WZ:ߴ{e+J~7m;$iw&3/gJݯ"';-2VY,lg/nc6JT6P*}~1̶'QDqa~|8ξZm?cJ꭮L/J;"~wNņ+{ϧ=hze}Cyv|=96əw/v%seTXFnӣr^|GʹĚ?uTM[HK%I7BY2-tďλyd%|WTǛڍ*ӟta+WΖuos:N9QuQihoa>!G{5`9{Ҟ>ROM)3bS⻄eߟ[͈fMgZ]BoʬiVg]S^b![,vӥO<|Ksu?:Nx7qG%/ +gOqUUhrFv:6a3or.!^4kk!3;>M=*!z9F[D-bwx߭%}7¿(6}gHK39rC.P<4$P qޖ?yc(js}iYiXtxfRNz7E\Jwws"ނ}'e."v`.3+9fj}">>iP!haT'KV ++M͙gpn*v_]q9]~;֝_0]J#. .]bƜ7EuDwy/J~QU+H{J?*0y?,[.?ZgлnNEX_prY9Tl_mZ-&xMN5}fӿoM#i;jLkoh%|'2+٦yҬg`vj™bD"9*2I*'ゐUT ulakeK9 #=L҃mM;s9Ex_$36yKYOtOOE̜aVxSؾCuz 'OyVV;\zm 12 K1P?L[lS2z8ebh@QܼYaιuƌOi <]TﵶΉ{?طB{6ǔİwiΩ:e S7Gʊ$-oqI;I^q m"y?,ʾq-%m>V:^.]i*vj.5W387=m ]?z:{֦n7{U&^cڲO/<6h$0%udֽjodKD+.7MaԆ|7Whl1/ݛgv~rw-l>+ͼ@rЙ/|"aGf+mgWs?ܙq|cd5| +7(Id9bM&xmuy-0S\` +={.?瞏5DIoq=˛~.>ny評7|rvj~^SٴKdއ5,l/ .nXUoZ_$/L;g6v7)Z^qyyKfl(lvOjM/X8ૼ7 |RKOzi%̞M}+Ϛȧ^]?ޝn~ח"ߺc޷] +%~PrYHKۮ-~\;+zQ'YE]-Ty})Iqc<"R&+{9-`61Qʌz6\8ق=9<6畤U{p.]3w^7YN{E6y?qP:]sٳk>OAq]…>MZʕѻqJ]Jj/]o|ClaGf^Zh}%<]9SVcz#yl&#囘Vp]XVYKd75hc[ݿ ^]V95'"3ŷM-\ +wR5>.Z$Rk -s˓)[t.nw=rVeݷTP+sc-+Xcg(Gios=m׼:iϟ[s[kui+V?[mf˅/RVM"^f.;i̕RgWFü]{^̞4[Z߲NOSޫݶ8j}'t6of:Lb=U1 *+{stٯ{\>=!W+m2;oi]9,v Ox^V)§z웘ʷJےC\k^zyzDLQ7*6[>6LT_쉶rH=cPֿgl1C1kOGrh2eKo_qk{\A3{(XtVו8 j~?&&yzKscE\m2kq>'{ǫNONphmvtky/Uo'4^bq>09xʽ 2{.Ga +%KV*lMoՖ#6t>)yJ +1K-+c௓S|i7oR݆{}nS{,RN5vp1aڟ>5Wᵝ&W%w,fq)j^b:9,9d7gf꫎f:7s +xXf~wdV-OcgS̶Ϫ>^^bc+7cۥ@Jvٹ_^,N}_byͼ'6?UٴEPʂ'A6άVޛ}DG6)Y`WS/_y9iww Kf?O+mWI>9uzƣ[ty|O ^LNb eyM4'̞[>og'v7O~IYk\Xwi~֡꼥Sj,cjj%[s>$`e,nS\h|̞䵉6|/Q0({z'ë']֨|[$D͋w{Y|:\vhgp())|wC6-'g8[5?痜YZӷ7b{X>i'Nk N}hqB銝ߕs9{3a{7Oo\\Y!ʱk3߮+?d->rSS/V2-BI;'e\ߕC6bf<[eӤK?YH_3woHjלXbgYW<}sac+ܹᫎa)Sn qhݜS +߬GRoG}0oy/ׁ'u+~%hwlf}׶;'u=iD|zm# L`zgd9=~rҙ& frdWrkGY>k3 {Ʌŗ<[0LQBչ]`iJ!OX +nMy[$wʙE۟2o_}vnKSy_{vwux[;W[?-Һjw?k?^cTj&nJBU[ c#ܾWtG~LO~昖qI8즆FZRb_(ZΑf\vZޝ}ye [6Xu{*Eg]Z>\Gk3Mu_St>;猢}2qگAlUZ3%\6*,#5\J~u)A_ +ܔݥzy_xľ]#)qa6_oޚ?=IfĵRhF{lv3YVW{_g< f̯)ݛSό3m߂Yɛ-YIdZOĭJc;I`و]ZVj'&Y[ĩ/ÂY +[0tR'_ٟ%/VM~}7)/;\2s%isHXqoCm*i1i3oͨv~M?j^umZmѓG +(ԭNsB'TZjqJxD9 +w,_\׵VͮLyߜ%[%uwOaXdesXfwoon. ܐi\Ƿ.t>`P4:YjI_qV_ެK3f?fzߢ֝ +844ܾSpd?6?3d7-0e0s嘽q6[k[?u^a5?o S\{Dj>|^W}w;?nqhזm)dW3Dw2ĬWbv޼OOȬ|e_v9S#̙uhv?9U'0<Xԣ"sWkj*ez1gz|c}g *6_\3'-EA'y- ͘.5[ߚѺ>*;Ֆ&;obx݅{Owuc'wc ';ٍ&5kռ. y=[㫰Ƈ>x3kAKtLhGqc]{Y^_6g*~yμS|'yaϮ?,Boi 96+wڇsc獽 ?shj;mgYuŞkm]F!kFnㅽi +*wZ!"uO89..m=tխjzMT /zh7/θke՛_[靻j,GLY]Wh[yoROwa;DhbQǥ{pp'-| >.ewr:y'h{ ?Ӗ?#NmIٶU|t_':g7K*ZEɫ,8,M?.Fr_4yS09̖}bή5YgjVnH?ú_]k+K.]m0[ޫ޻fJue_6̍X|OҬ<\sו%o}Y*_ؙ΍s#kG|O|?y[d[k%zdlZOJ.{!t@kϙJe9}AyqfS[OLv*Nm.Fo6Vyr|kp:]39E/mYӞnN{K8%nR߹^{R[$_gQSݟ%-7_27!JIؑ ?NҲ2B{y3ut%$lĿ:XqG,0rm?B~/#UV{ԥwJ&R!rS3SjmS0ƅDZ,q2Tpy՘c"^SoJ1ϑ!7ԐxHkMϮe{ޒO٪d~lq~_ԹmymQ/jXT3llЮ,i2okZ@ {&O+\}TKYx iHxe+3eoqp4ͩמjlO̷SXc`޴5oHVdnPxA[FӺA7Vm}Riﭺ|x+~Eķb*hJ0qRwwj1T^m#,oS0aַ#{_ݑm%v,{`ϿHUB9ojW3^?X>U+/>6m˕{/<նɆ8J +9,U[Gڈܦ_J'&l\~6o>{ +>|ftSlҘ!g1n6rC)L2s^6[! ;i2~ZP|yɷ +$Mذ5}ot 7e6niygX^nr:A{|\؛XVnv F??Ye1o[iz_kh[|oYFvK?1 +q)S!ʄ>ܖza?Q™ޕkυ~i6{klOV 6lVt}q" leTyOZ69R$%>Pqe~<#d{eߟy ?giT9cU0}͈ɶB*/v=S05𼹫%.E]p&y? wMYR:22=g]]8#k27,4:FhUK.ZRp7Gܞ5F߫0l0U0t-;LM\ͯBw%k vW=hy̴Ž.Zl気}]AWv~BqzysO8~)ϔWs/Ywl˽ldɭxT0oeYȗ~y+vٷ6QeV:v=9S ;۴l9klZxo>Qџ)u?1/WOWD9$[;|Z7l~;{*֯>+&2'1 +櫺3ycEMUg,zlB pu_lUދ%+ 0\f)8҇/aLZ0y$ +`壘W1ғ'c;`V[g $쯑]H;tr67+o꯻r,Bk֞>eN92=Y~++_{/Z[]xY_O YpVKޥT8[xMU[[rѓkU936iLfGmz!CkZ]>iP2Fȸ4}g96YGx-ΛZ㠏~ Omc-*5oaxt(oܭӗXS)7G׼`R_wpCpO]E)l4o B /vy_9}pot2"tj/)?{prGډ΍ +|:WS8&dܛ%JzWeړ3O[AvЪR ENYv?vVz.1^t~iu /w;&qM;ۇ[o~Lkayv, 5nmKPҌf;^$d\*sVjwLƻɻ^VaT6iR-Ji/eWū4oϼ}H7s#ϩ֝or7,T7WL9* L2N;qߛ22?K\*MH|t;xG+qϗ?]nD*c|m6Юro֫Y5)/7gxjyoHVOpv1;o]_5B1|F3{XcUzзV>vK~5-:cۆ2W{sA2w+#fs\v_5ÏOetF=wMl6皵w鎰nyJ }av9>`Y^vmזQ|G%y'zsL,i3h:6dJK nM;5&,mMoɢNNg߸e 詥δhLƹZN{MxرIݲ]sϭkvrZ;e7UT>.;Qh-^]2Yqq[?'˔[ӕzzSj-y+᷸Y` :kOeuZCșF`w{TgR,:瞢}"O<:k]ḩ_hUyL]My'lwY}xa[ێ?|y֚ +* g~ :edҔܓg'=2d cܜC|ݟBwWtƴ)3/l!Aq@&]S09FW`yК̒;[mz'l)l\&IUMIZϷ6i. {;CE)ն 9\/.۫uqEzM\tMW(`WSc~T J[p^IM_s͹7FJN9j.ޫF۳S}J8gJI`?켭~PVPvKzn'mpW.pw6θe1\;?9ofWss.߬RcrZ1./[y՞xjoGťi.ޓ4kv:ϒ~Iu z`ƒ%?ڿ]m36 +޽bU'<Ľq=m+~xw褾އ_<ǡ2Z%Y/vY%Gl0ۧۢOv[ĿsUW- ^:>zձ֔=SNm[,KP6cSCx"[[#"LwFSAW]z_~ IY}J^?b>Ѵ[/biZZEE+w;_ݘ:y'$ +Z)(*d.w\\ | mEW{dǵNn=yM d?{ughHso7eLd-%b̰g:*_%c{YK61M}xJVWǿ9őuJ[>n{Q`ݵg4}hYm_.gSk=z/^]{OMgͧ5w39StY+wBN0QnŔ}7|^tW$9oafmKW\_kiE\š +Y?~v0!gM fZ荀;? _pz˭0OgʅGSy,\RsyA$⅋NzuL0ՍN:"8]]d~bɮ:,ӂuy#I'~1V|綴iui- EˬG*/߸z"j $L:5?Kl6+x|YP,>yXE5'yDÈEѡ5ytGJi蛚e$dIWƙw7^tBôV'7-ްϟ/_z]6幁i?ܛ ,Ӱ{y)<8=GGEqDݒrfݥ`}Ni_5Ҫ|J4i'{-eoKYVu-׿E.5}~K\Հ CkMY8{'&L9& O%Ӹll?xX'E>{NW)HXnObˊG5>[{n/sdrMj]y+Vo +2L׵(Dx|~I*D[7j(?E{T>O֟"Ƨ=JSI|韾9$xnٻuvnX\Uė{A'MڨLI.7l%|ޔ˼L'1l}ٴH]xrksy$^zOjsz`яՋ8T-g7߈Fm.iZ4ű6LU%C5Kϯ:ukbǮvv|+.O{|K%%:<;-tVڮz]•oiwX]^y~l=n{T(?%]rQ\+snչn{'C p9a,7M]N^iɯ_6WJNnt׎:#m`(ؼ.ƭWKB")Vuof_6=E|-޵ggᄎi[95KDx։"ӗpJܝp^[- +W7νԋ|sLhi,HC춅XF[La텟ӟJ~yT.\[mVEO=<8i5f`KV|**xeļfəeS.>o&|g֞u^RJ?OӕnO\Ezɯ%?@ߤ+:uw|D琂ū5w>P2v M}m~ +.3%?6i1Kԧ3)ʖK'[9]Zz;GqDgLw;˽?D3퉟W,~lr+H` @PiK=*H^lk< 'œvPYlI[W3UN齤! ݧ/,8t',ggyO xuyӗdt\tjjLG|6>g_g+}UxZ 5+O=6 ZjKȣQ_gmɲإ KbxԄ7uWɪS*h\po#f VV} !8C )4m|Ɲ,TG0vݪQhc±A'sےN.fZ,+[;{LSoU{}hj|u +S_۸;l[~+~քg3$gڹ3N*5ccs\>p%3 +=Z`okr7/?vemtxRXgeϾvr87ThY ++%"w?t۞{i7=].KE hz\;#`"b3~*>X_jnɆ50Ξ_ _(Ӻ9'zK3.z6`Y"/o>C]UrѷK1Hz䩝ֲ}Y127⦏K.x!|gg7 \kv_쮸Na+GkXy -ʫ&,kGLq++RЛqC|H[.޺tlfRʼ'=<-i|6Ռ^B:' +gs.%{%/bPfitgJ6_߃"9Xn>*iuk~3re'2&jw!?*ĝ"1jU4;j(lvWe>TM EM5w`-yֿgի2H뽖~ө7G2^-?:^ɡD'cA߉\s\ul;;1&ZP`>[B3{Z3>r3Qڱ-Mw&U<{E^ąr%NN78xy[eXRΕ5ֵ/aBl ƫFrZ%_h߀w'etsv0oZ-2]re͸y;s>֮.wN/wi+9^\al/]曾0[bk4V?zm޶yO>ݰu1%^9.wXhpMKa]VJcƧ kW->Khc=ENz ~MWٸwĭ֗[ѺAo_}ǻ~{5?΋_f ~qjqdkDޫ۽V\Su]!hp&ѝG /ە_³WOEBJk,)sWg~<]^l:]x8H`?ir%);6_z9Q޸JjUTu0GZw6 wRI&ڥ0Kֿ-w?]:f19u0R9>Τ)ޞ]\xtp3h$߫ԿSSk>Ϲ婲i{>tM|آ.xuˮ"q˴G_g.xd٦&]咢Nxd֋/%qmI:1f{=Pj!` L^3sK_3܍m:gkeBb'#gqqLف}k͘;m[/(2q+<"ǫjr=SX{Ugc9-d_}-c# n<.7 +^~bz_Oiɉ)%?Xp#z}:i-R#_UWs&ǴW0+%'eOV,2*J<#/o5xUM&y-muڮ{kybԄ3gjʙgm_c{6  TaK>j/%/Ϣ[Ng0}^=ӹ9=ԾU9Ca_ezʼ< |+$sW4#ۏ%KvW4?8nK~w_>rA} wοeG$3Nq,h`׷0 Bg]ּ?#ՠ=.Y6,qxʽk͗48P'f;9<}b|G/+󵨐}ʝegʯ{독,'{}l߶+e.[ .8߃ƛ6(>$J}]V=~'7 H6bۗ(5A9BƜ')Hq H +_st5eoMA͇YﲦK/].~ᨀqEUiKOV$d- ;YXyWzQ>!L/,1m68DoN1&~#V;*Oyo2zxO~ЌMoȽK+H0×u`IQՖw*}Q|q/[0]ږwDMةuF"b3vy\T#hgq_9N"z<÷*l=Zix\k»{oj8PXSU"}~qV[-,6yf'g|G3A^Xv_^»SuE)go$-_m)x߮O*; '= \l1p#E-2f{xKaqۜy|IRukr)yE[-Li6ȈfڜoUԅJqX xǼ p$ȍ N>2yuڳR>ZM_%}ǿn-,UM5OῘQPeicyV9+߮z}YyDn-PZ_@cSD};m}~~Xe\{?zv?,r۬5$6uOX/5[ŗy^]%vV?\Q'oъ/{Zv*^f/=x 68l\Dܦio]\rQ?)8|߶8ͩ:6[#յʮ]q/tzK-m(\5-J;O7)z|1%,]mU>Quu_OW:3RP~ǖ5vzaΒI-b + Ϩ+M[EgG4;zf9l23EMx/_}_$j<4atte)s[i߭DF^p_ǟ$q>7`YnfT-j~) 3׊(﹞#v˪ijLyyRg[3ܞH!$'w.~[sU:oWf\1Gsrꌌړ#VwuﻰG?JL GXpv+\Sp8쏴ζ;uM,#-*7bhOO'XYl[Rւ~~/ B_bI^:KNʒ#Mm̼R'R﹞<7ɘ]ksJR뫏ٲ+{v{8I!s:wK6)j'l.R1&"Gq;}"#g(StimQO'O*;Dz$o>^yů꟡sr}kxLǬ[woQÚ͢OĽj_~}u~D h& WmY[~e^E-Sw%I_ $?2ۭYKD=&>-ϡϵUM3=Ͻn묰d&{!KE'n$oo]ּV}_0NV0i}{ٝB[2{}OzyǬ"2⃟0luV>ۆߴ!pˉfeb{74}lu%ҟ˼_?;;ͲK͓ Lj5(-0}b\B+2i)#SK+*OFKk*E/ZY0?tzjMxV¶u7YoR4xϤKpO?}*f_^pnGabv/g.&\xKȟ{bΏMYg!:w㍴z |g3Xv^ƼK[nkgҝZ[yp|KiB>K[['W]i=/NѿNCܢpSkł]U:]K:"dgsP+6͈BM{ msԖ.[n!Y5`AbslC\e%$YX=߄u+XK$x= -@(M?9躜x=gtu>)eC"a1ax ʄ<κm?ݏ~< NxO?R +X3Qۍ/4]#Šlr4;nư'$9\Uj,o89n J<¼~ FO7۷>$ٕ'i}mLRjY])q6]|$V&[v\dD0zlW0b%?}{5DjArS"V,yՐҢ,/K;ޝYe$FYLޙ+[.hJb0mw|{sˆDWfoMͤ`N 5?Z)k#][jpwmW "2;f {oz1'P70qUjK'TFKsq{ +uU'p2Ii4?4_wsfΎМr ~٨{IKGM1r'K +'`v5i/d8<׭{n ˔ũg2;'$|S[#uw'vo ,6OV[_(;.Jw;>my>WZo']r1TQ˕sN͝-_Cj'ND͢ZR/5xZ["DC_^S9xi +W3gtҎoέkX^w7{/x׸G>&7-I\+ۤο{}ۂ__ |oCAɯqdbIuU{M(yzWF YwXnpo֫K |vNѢ9Yo:Fљ;9NtɌQ`tE)տ|g,_?_}VnB7ϴʛo%y?~O^Vq@- a1yI{rH͓]6rU&/O;*z۪ejD喘[8W'/t?j&Л|>wnMdH2zrũxtߑX;k &{Oq\y҆W.Ggs:A۞ N(&l>Uwε{g_R)Xʓ4YS]ˍ/7橨{,!>BWe쬪 Ֆo^+Tr풧wƑS^f޽c}.wؕ_*_NCpv\Ks~,՚b0uxڲBg+w1HCos])9}łίK{q cMٲVG^jjL*TcWыf݌ߒsDI +ǜg_N]\g`M`E /Rݲݜr>[v)Q1yB˾<z /:4摒 BA!{8fI~XQGDjNɯ=ӹsM~,r$m^i֚dXk;_>J!h{`%byܥ$?uH]&Yb؂zƲ-V ?,Yv=Sh+[e\ͼ?D_}8x^{oQJ}=+. 64i=V?ԽsdORkYmo o` quiKͥ/FnQYIu3TH\5s Kr7[]J.zxBr Xg)00?M`D;~6̻8t7t#;Lћ!uΔZOKW-dOuj3Ҋ[0BJ*)wE>*8&3ԏq֦FS|u6גIss2\wa݅˶ rgIߜ_uww /~;|KvUfg,*QרV ypol'zƅy4^>r~g߻O-&2ŔIE?TT ڥ4'v?~͟*MhpǖGǧHf{g}(>{}>M9MJ(c|aw;o%f0 :v/j[_<bä?Eyy\[C[6pYEq%INԧwr\3~q.9W3ųiEVYWHԃ~0{w_IZw!OYnWgLʎ־\{G{Y]]t/)-}:$U ̘}CeQOjԃ;p[oߖݾj_?];>=b oLgڞ禱'7%7`7Gw1Xcúv +?`%IJ &KG6.s2IO߉t V4|C;fn9ַ[{⯞ZVm򲛪l2^BvM)&Moks`wR?OZٮ}56qTk\;8?V3fqTnݻ0u~dKE廙ex.ܻsM<}<_͔WRɫ,#vJAXWn{i&ex1U[/A9>\/ld'^S=5ncdG^d2,>+*b\_InaceacI +fObg5 $?:֥mT$)wu_jZͽ~-.`*8h|"ӵ?֛ .}s^zZ]ni%ΏUg <7g!5+|i-z#[KgV6iubuk"}\lr^}+)pOKyO0CiG:|Zf?c,&m|'5{vv{T=·Zh9#|Nj~Ѹ;3~)z{Kم-91 % 26SOt~!9㰝(Iq훴b~Ek'^ +2 ?cMڝI_\/ٷSӎ^z3ܣO|3WElX<_Ikw\b}{{߅Z'inGn/E18@sX]\{'[Lfiaf2;%}'>Y[l8NF%o|? ϟ;m鹈^ϑߴQX>x%v]ݚsϹz}nƑ9OE[Xǯ>Bwom.Kh@̔PbA<[_hll8qCZ:=}*s7t *_4uwTS{CFް՛p6JwsvފE-kR\na Yҿ15+J򿀺{kfU&4W꫚3<pg}>D=ѳާ04eu4.6UF@,['SK[[}R}tkDhnhzSF#)]}~O\ۿ=J=Ok2 ˦[(Ѯk~uY].8v_1͵.;lkU}Se+;UneER?,Se;ׂ_+d'߿K-ں+sVO8|j}(U5ol'Rm7 zҧByۙW'va6O?j˿E{ؒ)*%R%(mɴOiObx⽩WrŞ2I=~4aEgWmt۰FRwGs,<*">7ouy_̒PUGVV~7g"c~Auk.M+ja8w[;,c1!q%=xIeˍWhjfVL'sM?m\ZC_\~TŪ _CzN61τ2-Қଙ-rϛ>|,NSf-r}e;&6wtWIٶaUמlrf]X +l|/ڴ%MŹg;:y {x6{fu\*Ko,~gΧǦUuM>d|^^[[yO,]xhv`t=zgC1=/;P욳coj>XV`7_r sz )~]a 8~.cHbW%ljHhd.A)-ElS|/gz3K-D#e|۵ΧK'6+\/yzMov +L1Rռr|^tk1x(MR?Nol&3-hؼpu';.Y-D锗 ;*㦙9廗Uw>mLkhaZ맜3pw2s$pޑ=:$}I*k|Ufۏ#{%̜;w;l mۯ\'r^wMj+O8~%&6|-\BZ?8D]PTN 5gDq>`r[']_t^e6.ھ^,_D)'e65N(ڢ³Io_v;{Gi;w\myi rBK[j:|?qc g U.J%mxYeb ۚFVY=YsN;/H\G|vL/K;mҾp-]W(jk3MZv7j~6i%W3Po\|oNfX#XB Prz_؄ *?;woG,߬tbӄ'7>lzܛ{mw$sݭˢNy&Fb4I$V9mr˷\;MhDJviȚ!d~oel1\YdeS1mOj]z_nxVmi<;` |atAdӂ.N;U%ҟ YQn+ah&W]6{SojoޛNLŴэmJ3㢉7,۹g66Ut?ǽ][ّ&Sej+f|n!' <0CvTk/OÞ1o{\V2-9,g[ #ħ8V."IEz~GK&ȉ=ثˎ}ûl/ ۫#]!(p2 ]q2q`߱P Kj1qg.f)Lgfy{k-Yn>Ƶ1b3LxN6I:{I?\p_Ně3݌yp4:ɬ3y26ׇ8a /K^,3źN]3u~uB*斘FJk̵;ֻ^_3|l՘gx\Pjǣ<=+NmJ;l[)LTX3Xm'K14bSRWRBBcE3k:%'[|vȝ-]ɮƴW7#$oT +]z+SJZ;w6ϛժ7.|PvCN͑3*ژ9'Ao]> +y3GGbw}Gk8'~aǛ6v*䮑Q{䎢> rkۖJ?M2lEX~{jQ~Dxv/ͽoe˺ƚW:1=qwuaڧ25)ϟ>q/犜C$1 Xf*J/y;s6긛} Wk>O}ѝbfhSmmӯzFkIGm3Efק"VM mStLVUv:["j=1YcȲxrYBԯA׼m:zGV!)IZǥUXR}3 ]Wyn 8wO}se5n +y %tFYɍ^pco>dºݫWYli{z0jYe_ȿfΚL8MmzWupF{zTzXu㖧Ow:Ӎϛ0S#"&lUg|SOe<_}fel+/7.S{5Wwe~hZu)O]Oڱ_spv+fδuίmo,eG׷Us@r嵒Wg%0_2t!s?^(&:w7Wƭ.+}o7٠O7.qm=Ru%$-9an»ީ,f[/y4UM ;}n`Oo(i|מ!ށK_5i}x&]8Jه^ jpǰ싘oz Ȩ.[u "y#K3cxzF\qM^ٙ=JgI3;ry֋n]7;Q%'[Woι^P땀=r +J-29e9l,te ~̯͘w1q;gM;|5AVvQ4$)d }݊b]_㳊Ea;g/[l?[z7s$gkhcޝ.̄M_r2qׁ?R=m*?f%HH|z+~žFiW|X2OjzU!wSmRwZH,Z""=C{),/eqʼnp~u*;ib ղG/FV[Lkon^Z?_UOs;yҡr+WE`X5k@7ݯtي5e6=|~h ?_xbz%Ej~>YW0y!5Ԓ;l/ox2M+/z\^?(^ +~{q/*~G?uBԺ_zc| R^nN{Y{p>G{aR+>ny߄jznA{L^wRV>}&;*u5ϻQ+]dsN0|l?1n{!r:žDƛ;j$?i!}͊:&N;8lyVoRo3yhY=C޷n˲^*[,(q_T֥?+ Twڄҝem9PS䴉5=To_京J#-13eɯc.?h8d&.Kb&}mջTqo>!>{"oÛ[r*^O{9pg]n幯Z:?gZ셯S+>~%”ФCKg_^N³1}NTo_6sXl;a-ll_DӺy^Kۺo]Ӌ5ݚ^F+]$ϝv~Yx/ +oݼy>7x!uZK~2kek2_mum( 5RSZOe,o[] & 'Md{oUn8iRcXwOՉesE ;E+zG,w6T3rnq]BbkVgs.K0m-7-<a}|Ƿ׎3D +MlrMHݙV(?z9xkm؁識fC5NR-Ձ|?nĽ4YtWk~ŕs^Uæ.<6ALǢ$85M^< gEȃ>~qYa,y5G VϗlzʹƏ-4͜5$h†ew9cwαgE-U:kϟ'B9?tO6/tǙs.=I霺fRt٩ +=_kacw !ۭF('O.(Wb5k7Y +8GcbzYϫGVz)pi.w/iJ׮P짦Jrua{]Zeǟnq~d kefRv]x-kLHm +^kܙ->vbG,CWs߾(CWkrګ$˽on{u^\] 2֞!QZ^F?ͱg}iwp_EYr޹t۷"Y?W:9k ~|rzeشk +52%Jv+d/Lo+Yg1/f U>avkイ>ٰ^I;i% >((l݉,ko1ąv1ٯ<_ce'Κene=޻qBR~+3j,|g<)yh'ncˤMVM|sS?F[T[o_Uxp/UNp$}<sŷľ/ξ+e2s&gV%x){?DhX|-ݏk_-/]2aRMs?/μ\h-S޾o݋9;I؎FN2fk,*y7ߌ_O~Xt8QOLA&2/6h>ܦ|jE$SLݹaPJPmث {djV.\vuϊ>=q_Yv>gEK'ka+{ڃj<ߠ×6C}G[ekgTbLxS➮R'%%LJ粕2SwL0(ľ+o:&fzg n#I/~KT8T= ޼ܾ2﹢Z9[Uybm$).XȘP96On_G^)?^r1q%JwN(z 1w6b1~| +wV` Wn]xyS +eɇDȻP+m;?V/ &ɒ}BQIϼ> ]c򧱯Ӝ8/{(wEr&c'vtJw;-gZc#Sqr0vɡƒ6gh\,TѶ?Jluka!W}R\}1޼"ţ|zyꖋw>mX{GgE͍Xfl z{g9?ݤ*:&k.}{h˚N7oi͗ߤ9o1vawQoZFޏMOHYX2sg$N:uCL[P>tC\}h QR͇|,k)67}uqQEs?Z3֮IboV{I'Y?VnI&V0Jp7үyP5G*H│1%9cn{V٦q>g׹Sikf[qCYOtuz.qjg8j#]FIT4cf o|a}T н"F"oNNucRrc}Ku( mM?5iͥ继ܬmVw']t<~An˫Or +0v2iUhfd-r@$ +MrKC;/zb3?1ybl)5j뛖˶J}'ڌE_.|Q_E֢2e&u$ +;ey˛>kѻ.*=~]#J!1:뷶 d?zoRvoxlwhÌ/^IN["lTgj*Wk72iU]VB+o3I?{ɼZKr]ҜrltG;͎KO_^RR}=X =z&Q1{|yӖc:j( r7f" S\?k]oppF2ߟyq^eiIa1>{f.?jisņ{$sHbLÂq2;oY4zɡI\o=p~b]qUΠqtGNTytUbRBm>|iʏ3[\'X|쨴F'p9}9Jܜ<%NOy <;Z3mw3 m+x9ukNl&t@y6s9Sػpʱ(|~+km}B)8o3ynųJcCܸZ~)°UTFߧGzLZɴUz4jyK9NmNjT)x^d6x~fH}c}N]Wvfxl$&SYb _N>#_TznT^dt,~ib/,:&!Sl6o|{ӳ]>WtΜP)IUg7)^y!3UMkq~nOfͲ=bzLZrA{cV{:n^6:/뮰/}>>QrLWwItY \+Sfq>ϧ/ϘwgdmY*/:]^;-;lyex/ie}~!6 e~;l>O;ϴ/aŜ7{S?ޥ;[NYI>UD>g.*qYr4f2 +K\4ki)e쎯I8YkL:F?Y0W._gذVbB5;;|>.õ[TbP7? +M]RZrCӨw|J?n^A?owiĝH*|i/o'o*Xƙ}z񆇢 I:4cƵ;]䥒y'LҢYRܽo)mNhgjӟ;fRWc̫Z_4APiYLs]>C'Gb5U^JT\ITԅM-)kXg>Jg|ۑye [^_y]7Zv/c,K{y7-+ܷl]N`گc/r.՗nK:uu3G?ː2=lׯ|V-}/̡ñf-Ǜz ^ߴ{h2۪o]yrWtMNYyA˺m?T27L-xfۢw3w^i:%b]weWV;њ#q6?bv,~cZ-+7]9ւIM/$+̥&px}D}qlwOzR6!a뇡d49Z|ʚO]v{[ݎDza*6^Z-uǎ'oڏZkWhBdza-.ϖ.`i[c?^zVק?'r56\DKOA3O/;v`=${~y달q9PY+7W%>/7׹ zQss=s.?Z,pP<Ҽ$kʨ'MH1u8oEݍ.n'|'O?--c+?jYekԵȜr1>^ }=tOk5{diW(| &nʓKr2Q wn3jlܴOsfkusN`#pIf!Mr|>3[&}^roO0CGƽ^^%=+s~:/_SLp 3{۷=qJȦug}R|d WzI 9 ">l _?N7]~L-; ίǃf\>Qpe8ĶWu٘`o5Y +gq-0z$X󃟞 F+cV8CA=ʀw)?7O?ɈKI;{vmQp.7$ l< *g.c|IU;+T{Y FM]t+8_^2Ey>ls uR?`u3-jMiiqĵ=It9i2}n۸L׏u5 ;;vI1|JZf2칑BonMjC +OUwܗŗ +߿JXaD^9îuF͚wIqZ@.y^e;uOUQ|T7q ʪΟyn@Yָ=LlO-v0'Kz̪W +MXrA7N߫.e!ɖ_(y|hwsEy[[ .{~|ծL{,p=;u;ưuR|l_iySO &L}dӯ_ݩ[cˍU!'t1Z#4Yus=k YsїW>Z ,cLw魙a_xm陞GΫn*>mB&F^+tK+۞0kzwIGN_h){Mի]#_"2_xѶ%3$˗ڭXulӹU-EVl ; [ ,ԄHǪwžuw}ʩ^<_KKoyw׳{+7a< X6[YUq`f (~E{V4J,uݷ#كUj^ ̴akcy@[_[ >?~^h,6iZ|J7MO\<{wR<1̬~5ְb]t'L>eugn*f+#ϧH) 3U]6dz[\Q?z>Z}xpU"u'[vB,v_QI/~m]\Qev%wP];K5fk:wÎ/b[7+#;Tv V?="Xe,:bλoԤ>;;Ej5!f3JF4Fl{2~4E^[zlsƷw?X#fms!K;$-Ly}ltK94V\fӶ4fkv^Źҭ UƶcE'sZ)5R=},L.{}ĪYI۲toiX&_қydقm{C,Ss "j~D15a3:欼]}l"!!NƳ2_:X:}U~}USxR|3wF*sa/plE#ϓ8h r/w;|G5ߚ{ty؊ 9<]߻YW[L)8hl `?a* ўgzo> la|p#aSNrroґOJ:-vCMW7M->Z&/bS`1!.T~:65^و"6\b׆=^ZpW)xr=}٣ϪND{xN;0Us$wU~6Ya{7?റ)Tb+^gʡk)lP~n1V,r5%.&X>a^E&yт?gx[Y{7KrOkٿ&iWRQYYboR&kشpaLzĹx,j7rLcrUs9F;#]_WwG*b'{1)F FTصksW:|s-GWV!Ϻ}oalyۗ~|X=],pVåy1[Wnb%}Ÿٜ[v~ΌunyC.yJ](߷m۶kZ6iף,baguͺ +֝xI\ӥƈܺyg{ e]?&5iWL4N8z|ނB.;|r$c-Sv[X0q}R^-MoJ]Λ̶";bʯ:BR'򊏶F=8Gk{Vll~TyNYi1̞>pkJ.xF/N}ܿԙ;%&]\ϖWK_lY`ߓsma ;oaƧdr)`pI܆G[\̵}!_xOGcY^~8!['ӺGkyrn8#\C~9RkٴZwi"K>z,9cu,5'~yO3&ͭWܮ~]cM"峖=-5Gh +ݟ򼲬E4fٟ3ݝInan&Fj8p얰{QzByF%=26LQ8%Pď|(%&$oL}pL[R2l w=xӻ=FM]qF Lt-[֧E{}Wܹdl#u_6rG{n|? /L\dfOw/>bdϟ/{PzNj1'< 2Tsi#V6h 15Y +e44[չ~9Z[t=j6̢WtUVaɴOgoctҲI!qzIr=rqܷޠvC- :O3;f7-P5*Y+>׾~H{S_}2ͷ~B瓎O_Yқu{ ^kWF;RξvsD3;N/nzw ߶wp8qgXݮ>z+xr-\feycŹ|ž_}SLWug8>mrV/q\/+ch#UULb?N =lL4'O(Ӯj ޷Z!e,z6d6흊~m븘\lx2n}M"/odxS/7'*KN{3W^|KT̻6%MϴkܚMV9ߏ[Լ+'6UzW)w׭ >0=\oY{~ĠU]3aC7Gf0v7]˘亮㧻<;hOOew]~f&O?ԿsxC喘 +_͕-͙R")ANVzC1gΥV>wǜ{̞MgKc֦uxڿi7?Gq2nS(1x[86 Ed1ՓLQwFOBI#쎷u6Uݵۼo2Z.]`꾃""V_fo^ޘ䚐?1?[;5o {>-KC9 8eOJw忌S6B5צwwDڦ(L/ۧcm"L֍9 m<+Q8b޽5@irk.S&vDwC9ktڻKK\KׅY. + \ޣ-+FYj\xUWY-9kz`me&8agl3ԵΖ&ɷ>|w5VмEV -_BTy}bW_n>ص&T'kV9m~y3|4XVfvg-\;%)&d[k]o.+s%; eyOsafDWj;]QS`vKny&ԇYdwv'vi埨7;W33 W'd5Wb~vyy+Zl6F͢'UO_uYxbV'6ѤzW\qs!ÑWz}Btu~&\f1{:^v:z`0fsR&M=i̱hNqfI6Q[kq?ᶊ)Am^Rf_a-5dchGGy1sY^^޷.<|;'|ߨl.9%qź6T?yqAl7fz|Ձ}G3Z>~9Yuǿ."ԟQӸܪkB謺kelrbjg=3)tH?* + ;FZtϔה? =sˈk T٬{U.-/vg\H|z{N?c7SnC&;uu?N%_c5ZbscWOmDXY=t2˟{+B&XoI~o 'ɚ YQ^Ty;ҪoL3Q(e_c? owJuNax;ʏVP矼`JOw +J +/5qCio:[_|=VQmަًn NϐKuk˶n׹?8(it^wgR2+>ν$if|׋a^Nz&!O]FggW*kkǗV2}VH6x֛p$bƓÝ|O\tg4r_=ߛkj_ _.~;{SL \O%|/(ɇs.>gFu#sNpYZ-϶^{KoMZ_/J|U͟/fvdeѿ^|iBsx<}|Vw\kdwzl}Wtꢣk$3{<ƵP)gfݦ,[6rz4acZ kU0fz?o㑥ϟ| <\1/<<JZf~n:qޞ }LN(ś]Y5 $ +WfY(V&{>&&:Jfn6WȼwywE:r5uǛ +E+NzMUӦ*ZVtT8cv˖szb3vj )<-D}Nӂ/b^O6bGw?uJW$~qeO>#&/_v͔o\Qb3 XRb“W/˞{Su#˧MҶ:~镍;y8uSmZʳ\oy'6l"ݼ~gsO1EH +^Q33Ek̵\r{[hV*ztwVߠXp{ox=)|=avhsўu'>,LIc7cRCO7j/-VdtyԓI&qIytLvuU6W4lSwidĂU!'8Ħ)-+tͭBQXHhZk,?(Ez QI_rd;v޳r?[V&bOeۼNoBK9.s=DyK3͊bN+T1:P[mE>+Y絽Ƹ9_ݽ'p^{B SҌ=m4KbCޞX_F-&'<Wja3ߊm;("|nUo0/㵷ϕde[+ǹN 7\fY[m7^Jz6V-1z%Grw99{pFh6mO^4 _E ;˞ca4S[g2Еis'hEC 7 I)/^x6;W2a NͨLr)u Gbʼ̅<$'1}<2Wt+?,s ˯ШT3+2W'YT9wS3/{Ľc'5i\bL'35;L튓 + /x4%f^[{JXvJO=Ol>dkL?<ƶYOޮ}/rqbn[~q ۾K^R +HSX바D7KGN1L5;Zm?<^Fw5g=9iԃb[.z塄c7h;s_EMaߍ7oەWdži17D[?h9lؕ+zWUC _Oc)U.w`03[m^Fæ;MlruJ䗳U7x)>cs٥/e=[wVμEuyy,wR<]MenqkaA9 gXz?`[-q5ƌ+ߞex˾zN,2J/z*\ Xd{D#g^[nb17V[ͻF<竫NM%vbU~=&s^Vwӂ"[40N0]Z(5o+!]LmVm9Y{;dgLh#"?IL 9$VNX$:e}?o[qEpiOfSW^g<|_80YAbnܴg2kht q[u\C%Wa"_R%yK1Srޤ<|=Y)p)jd.(Zřڀ; Pa;oWTd%{Pԯ낺g/[!tfms?&ײ/ }-cێjQnbʹgƅ2B_R`EdβVM_1X0^\wM_Xĝ,g&ۺ;V*~HkE9!qz{z,`Ot;,o`UpdaYل&.9@F^.w/Uxцk_n)f<9TIn%2W-MՙPtk+|\7L.-"Zcr3{|fow,eWnퟳ`Ex !Ϭmn9enߟx僭-';YaֱoϒLWѝ7:}>\Ꮙ#ڽosT)3y;|8Pp'Ӟ%\M{VK:B6?g{ay#ӹlǂI-x2MLݯ%+VwCH{FE\ + 2K/V>t[s$j3<8"VksY~17ח9!nS"SoiS Sr=j5ygS,{!c.[9ۙ +5P=Tߤ#^TxBޢBo՗2.zmC3$|R'R?+3;ʪ# yxOx,;vzdIx4Ս=+Y,z[;//?ST M5H-JΘtsِ%+dӞ*̙Uzל +izt'3}v2HHsn<梙\9ڤ̒hp%8ܹy}μ5>٩h +-T]۠Q)To`)Pb|S#*Y 94e~p˪'bt{7K^O+G]4y3N/%lOi*MM8Q̯my'-:bj۳S" +d]ȔiU5 mHq铧}ĕZ%;2cJMڴ*O NSxfSgn4{_>wI S嘹^UCVZ?Wϋc_EZ_*y|].L2u.~H45}o|[! =tFԳیZd4x̻^%.g +=one3'TTwYYxVC՟R6^gٝ:uL} ) +>d2fk<s)M|C׏nJy|mbiO"\Vx0Inv_u߉ĂK&<)6XŲ *<>м"SqϙZNM]_ަƎE\c^u)۞mc +o=oD]I&\ n,bɮr g;vgb8ia <ӗe~{K|[mzcԋ7^z|t `̓wL,7nq$>ZYWeOZȊj?>ְɺEX:;뽹=GؿI.1Ky֤NsҊI<auWʋ//&¤~ 6/K?񮴴JW%ٿ@Ek.yv e1N&ɚ\%rbdBN3kf+'n5Wަ;js⒭}ykwi9_W7]{;%ٜV3_xE{m9y`s>Mk-[Ȧ sZM٢wco^l;Lp*̗GWߵK￸noaak/keՋ12Q)q_-rLH515ӦĆR>VH8(VQ\wB~7O$W$ m輩/%X%^XW)x;cڏ2WdKO]²_˚B' 7}.HOLDŷA ~ݵ-opN^s^g*yNϽHewX= U`RnŖs /=V]s.i)bUT5]{TQ|R׾=dBD:ul keiϧj n+u3\\{aS$ߩ:e&ot27[[K[no[Srڼxڢ0^h:T=ۡ[{| ~|ܿF~ߢ $3!mCz]._{s=nE i\aQ:uJmwI^WQZi#7a݇+98U5…z]([VRuϽL(nŜ7R_Esܷ\RzYG\aQ;va[7Qžּ_aBm'wݘrBףG͑|p[# +U6y4IU_w~cIY>m߲ػLӈ2RK[:"v~?U٠ic;7ŽYu:}Gdd+Ǟ|4?:sFw+ NI\ oEdӌ=0U5R&|qekǯgOkYtk/s՛?u_O;[A\\ .;(~Wh}}TOcϬEGoɮIT.9Gn1x>һLuᵐ~]yaU +kRݏֱx+[oqlVxQxٴ5'3N`h_w?\gzN0W*zǟNMkǼ\.?mG+8uҽ[ԭXܾM/y0E|l"mmX襕q?vi _\ufvLjޟ9u|7{W=.q]!ykM L,cyf +yվDžEjW~{}ewך9_Xqej޺|7C[ osI%G}/>OBM/&oNz6|μU-}hQ} Vw3Wonp8@ѕa)sWlVo9nʥ#MH8'Ѧ-JNUu[,]rᶼ vV&\sMHI<'sw6SAW>;z^HAڵЍ+%缑9;#͒ջ -5}Za!Oons?޶W׮>>efyvJ;Efg=V0#?qUUOK]k˒n'=Um,٨6q͉bM˯.Y/)?gܷSL,L¼0Os<\ /poœrhmҲ}gkɪ2sZi;?\Ts5{(h9T_aOGN$=_mIߴ?JXǠWa.Κu[}/G?thmأ?تOR=7^=zP8|Ga3cmKtigq^頷8aULi?߶~%b6 `;޿2,?o2e鳞.;R2i2f%:[W\7d5|nJ>pv\Mbz.m?})x?5зY~U&ϭW{] +)/[`f]X5=R3?]nxdg.ʱKOmfg_iPsM<*$ yk71*A?aQOul9./&Gު]iv\z8Pewr+\:ͭʌ53` GM#<~S +xo/~øZ{FB~=R{aS)?8li{J.O[׉O I[ˮ F:feKXsčg\'L^"?x"{+`Qdpg:gOm2z,w}uK]ϊX[9\~ԑ)row,yZ%zfy8eAFhnjU/2A|I<kfwW +wm01 m/ڜ%UF_$I3x01㳉zy-.N/䶾U,J(!_b.늝kzg!_sQ#9yޜlҝ}Kdy:0W&Ny+Oɬڣ~nQ2/+lfjmq +~p֖m¥u-[Xv'X|BpBkɫkw0ee2[t6Dw|_kʝ%oW +vzʇTEI* ^~v-: <Ց1Q!H| f3jjF1L-B=Ă}+e%,zߜ1CmӍ"vF,#_Εu|ۖ0/wh쏏N'cxݣĕ~)g +O*_(Spo̽ܽ8sSޚS(M:{e̟ +qg:uO^k1)է%a{zB̫_ԽV˸)@?J\S[]Z/_ՄΫ?n|ȏYi[>K Zgo6S Qܡ"{K6/ϋ>zޱ/]ﳊN+a0c^Sw`F*I}Y䗵 / +u8t]Zz׏l8wɍYk*N߶Uϖ3k,ON:`[x<٪hyw~$9T9O-z);/mކF/h~F%r3].Tq*6^pK,ˑDgn1ɋ{ɴy-(P_,A-=q+]dp_efi&-(}|gs?s^ +gU|Z~_?ˌQN~ul_\l$K>,UOzhyB y vmxqqW9'H?R/rsWV{ hwpeiOҼ]]R؝bߵjiu˧3/TskV?)薷ܒ79<a\sM}{l9T1]kvwf낄6lZ.nUS% NidPk[^eٴ,_C<߼s3l&mשuhݷ}4ǯ)g&zǔ<6ۛTo3fXu*7lZbd?V̽:'rju5~[\~|G.ǿͯ}̜ݝŗ)ݿ5˜j/%_|~H}ch`H [88+|&~yNՠ]˥NxkUWxֳ(~ԠKՄHF,ʩ4]P]kԜ/)Y`5OJXm]њmtN9|ޙI|;3O xR*.}mƨҟ+JL>YMk/xhϐ!rjU;հm{eet1fLiV<]ߜn:kǍ(M%ww-^/׹<[$/[U']:qJB >4TxAA̪_^];Yט-ȮhIJG93n:1|E),/j_\m>VZuzR@cr{m*.6kBN>=jX?Wu/7ܴf.'me}al2EJu4֥N =%ydw&QN3TSn)ݡlDF^鞈;Y ϳ:ם^`dߦe.h۱_ԽcĹLrKɭX +!v߂j}l>-?'3hIUʧ_huպ_U1xtf$޻UnR2G}y^Ux{c[;ɷ}tf6L7\)~Dqv n\.[}}j{gCdɍu/|ΰ3٪O&Kћd1oIs[>lt_FSkWuV`.g]+,/X:rWsN+FaeZ=3ivJi")X춴> cT;̽\X>m&s4OGg.s}l?`kVXbROOOb<Ҵ9Zstם%q\2P_y+敷;;l9Q;ݣU'5sͲU|n{/ܟ^ j_|k[u; t[r^p}//R:)k {2/vnu X%#UݳNԥko\b5WmjMH0YZZG5pU+&8d~5U$=Swſo~`uFyד%^zi۽R\1HsM:-? e49"^?a^>=N=p7WZΒl!$}{h_ 2K{ʳ$|M܉jWu&nJēuFI/۶tBhι2O&?QuǠw-{.^,[;⥃[ 6~w-3KJޤb̶ۛO~mt+[֖q0>= ]QQXM3{\xzcmZe0A :>j`}=4(佞,dSޖSjP_.l:km>m?vړE |KO̶!l$poW[}+C`5߉ ׭uCb꫓ۧo-uPd*'*M~HN7kf\&:{ާVIM{޺ڔg=&g+}Js&2oڷ'>P9C'y!q\x"u$EͶ(Wx]&S77q:D>bNBNlTy9Gt"ܤ]]U"륦\к$):Y]-vXO,5$fO*/r3f󳙼5JܨŤH6 ֬VEL+w,}Qu]R{7ͥnʟl%OsZY RW5}cK)k̙3k:9?DrkcQV8.&^vʹ+745}O FsUl\ս,^X]Ó;|?;s;U8kK% C|լNpdMlfvbZ0ӭß/~oBDٗ{iI 1li=zFG|5[Vze5.F4>jMꗮ=*7O{`ڌC?:3Ou ,*.aWU&'}]_M|`+1oUN}&5uMzf +0}g(7_[D\Rx~} 6s_+nQpZpws ,,Lnɶ:J麟LnݹcûD7/-<9Cdۼ&HfK۽}S<86yZ}{Wv϶_1TqNCOsZ=95ˠ}kOUEnǤ۞x)yO-guK{+}Dp\5iSo}}NjCj)vuu_d͒҉YbM}*)SSYI #MfhbukS4_ ZMEs{U3cʮp0԰6u|6=]8[4|x)x ,γcaꢏ K +q|S7GgY)k<_fr?s՘vtB_n{adԾ%yM`鸐i`3GY~cAÿCkn^(,9yimv?VȪi|=<3L2ݷX̽O6(*6VV_WȞn KL1esv;{7 5ey2S">|R!.Y~\aӷbXY~)M AH:T7|Xloݓ3 +34N})ionθWz|:}BU ȝ5_Y3 Ff,ϜPD3..|~)UWww7ώyH#-Yu}+|˿лm|#+[8})tAuHSֺJ dܾuʛ+ByIx[;~Qf,+tJQ^+ IоoϜ^̰̺|6.y9%_~Yuz^w&˿vM.0xg4Vbw[Ha+׭]l枦X)tæv:,wMK'(WelCOTK|9kBUf)f>-xɺN#ko;>7y?`̬zkzWZ0]wbU-y]|qcȘSJ.M=*{&QŬq o0 rb(UONY22WδhI m7Kh6R)|RiO8p/55巛i^c >}_IcNI!v-2mJYACW]g|ludk6/BެU!%ܮj}KHpɇ+ #y5 +k7לz`rG=dpk`gwKVx?G&o9tnS+p[psӟz^Wܮ&bU:GN>1E# ~o4w/Ay +[;+)xD0߿JYTShY2%4yu\|Uϳxi᪦R%-3#- +z'i1}_w0l^H|y#ogOْF%ߟq`ucFIrq5M.-~:9ǯjq;G3T4v$'nfi,8&Jkg{ [*2O{%We_?A9([WG}D2aoy-آ7]ju<^+Dg7{C_= ޥ|mg^q+EYN?vruzz +^\zɎ"'' +<1GOi۵+.D(6ǥg]s,`X"{#m)-hc^bZ S)w>+qU +>Upjh1{!㝳7y"䝫;\S򙲨o˙r8j[$2W#2 ?n#MaAeYN6Zزw֦̫|-P͛V ]?ݪWne}żjj9ܮ V"G7xKK]0|~n O}=|0ܮW]~~ZcdmZH: +;V1x{ϻY}kk/wA귇 >ej/rRi^\r]o5 3;Y]f3d&jtq›M:GvK%TLbW Ven5KۥxK,vYbOE/b~q%X:~@:zaaVyY!q|y[>|,U Cn3, +=ܛ7R6Ǘﲮw:|]Wg&?-ʶگ]_u\R|~ᰤI5"e7Y"75Cޝ}A-˦'.:;V6}F܂głwsغ o|/șU{zťk[w?)IoߪԖ-\nrkw;s̅ZMbΟb_/^Uߨ'-#hKOy +Sl/9ڒ7sU^|̩^D픉cY2.{Ie̟fMx;xW\|jό/ rθ"Uj'NrsbK}`.ju^ls)3+7+s-֍kdS>߰I,ŠGu\|#2oĽj=N +[{~/U5);H\mSGW;>tv8l|=s.^`꯲PV,c ,,K4RYDeN `C_~.!Ȩns]B;j~8WDg_ m}۷>PҕW&q9ta|UڡEn\3wM;͝Uʼu^ps`ˢ򃖡D/{b#u4eWsMp.YSoD[o\nJ9 +T + j[%~U u+ b*Yֳ-HDfu8j*g\N*$xL_Kⶾ c~,WH5bgK޴>ʏrr x˛py}VuSӅs:O}ĺ4'~Vջ~:KEY\V%=O^Dk>;a띂,#])8|cOˢ99gm ;2͢+att_%Śz'BsΝ/lO82?䳅ff/kͬ'dVИ)|5疵;ٔL,+"Nqb!kuׯD?=qKBMq#GYM.8;˺ֶn+sj2_=yޜ\e4 /Ԝpȇ㪶DL ipF\.O)5n\\4e&iU<4]R ݾn8kXR^gW^[d_؟__84[ Me6~rIUQtoNf|ףr|u+_ˆYI[wnCi tT+n2HYz96*e];ֵu,o\;ߐJӫ+^rITBw. uFnϾljp7^kW?tu׬[{RH/ΑIԾ'_/} +?*n>z{!.)},\?|aWbSɲ$wjFw~VϼW)sӎr>͍?IyYf3 R!k{4[~om\p*U۾/{ p_ ϔ=~N*iW*xvQ|7ԑɘ`{bFFVmɉS<7-"w* ;;[D8 +n]>ICW0^ϡ@^ '.l)ԔNS vb35=Ybv"a Jcj7uxDC;rTQ|ګfas|+ZV܅_U94S^WtF%SmSK[kUH}5E1ld_6{wFry].϶Cۣ)h>e*ީaB v*2}eq}u-V[59{%ꇹ , +շks/xqyUW?v՞(!B_6&i].Zt"N'q*{f璶=b"'HW)Ϭⲩ?tG]SzQDZ$XmwЏՄJMoNG7dl˲\l~^朘Y.Ϧ{tj:u cN獎h?<=<V&]9^[[6]J/ݵ_jboݰx75^p-K&zx-p:o#7_, ɔ&Rit˩TJLV +a'KNۃUWqyhg:aǫN<q4{+ׯtmҖ'OSeuŮWqK27{w=J]~;|Pl3x Wكy[Mez4:q~?k=7t u_l=p.EcM/9w$ۑfGkb9AIo-d,cɲQm"Gf?;W}/Wzsz*5Yɵ%sw\)KGn-v9ky~]vE}YO.9y SC^'ӧfhP\w|swy#'Ջߴ[(ר|z iǯw{=,u>?H}P(ҫ>_{6qJ>~&&X~+1CϢG{ TRΨgœes+{erѷWWsȹm lD +f*uꁅ95Np];sVk&vLs(y,uZ\#yWҕx`d5wg;2WA<%uҬ]ӭ?tmK⹅'_J76`~ʟ34{H^\ӿ_b+yLFl#ɪvCWYOocZmKGevOU>="=_DTAu:-N.bzǥ}ۏ^Jg7_"Y~@*H Mdž4D>j0ɿ}gm͕TXQ/#9~Fޒ15\>}=?˭ cY@Ƽ%kE{w[]${ƲZ6s:ֲ&Ƕ_vgz`gq -=Ͽgl4س˿=wWƕoNK=Z<ʞMwk۱R&6ؽiҹcg]1J=YMߘ_qw%Z_P2`^w4k!'>:6X|Mɐ_gz9} z y,',nu<ӟ0+Ǘ5=-:âo|ϼx +=++.邒o3.rET3.Lݯڡ8qMNy߷ +9ǘ9:vWw,?- zG>{pu~UطʛLK,P3V}uMe{om'-u3Qq}k}[rG7$Ossa©$0CrKN6mRˮÜK8 x\Mt{vgcb<#:5b'Jn9{1IAwzѹ)).ݜ^!~EbKp߽(>]OQT+x'lμ Ә} +-/t ߪcQ#u+6?XM;M+4CwęSE.2Il#Mv>,S5W-^5j[JC+sU{LY :Zݏf[ޘ?Ÿ0$u沮Rcʸy sԆ2ô0+I#vZgJ>ݜq3_^^|UwgК eiW Prm@֫R+7|:xRc6b6y5<+K%ŔɈUYfy= .وˤw=57DiG̛w7iNyT͹>FW5Cs3#^V_6cnw%&0XS~ܡ]0gIWӭ1qok ҴS;J>蛗q•9 :QEfx6 +؃v,Yy\tSh߉sֱi3Nʜ-zԠ˂e]ξ?om#3*,UtAJV[(9^OozєK]Ի肒؎Xjpԧ>2|գri]NZQOV\z`j||Oy3vr^6]m8Dd+uIM]C6\|̽KJ0sγ?->>ڽ˽k՞(kfϵUM珓F'UOxW}(m7{7[X)I Oq\6{rVwW2V0͘w'9z,kQWU{B9'̎V6<ϴ7ٞí˗ݽz[y_|=[ԡU +Rߘ.]ܼ\Nzu˛>7ZOwnySE\_孔;4Qx w.szDJnvD3h3 +Vgt/{'9xMElY&؆=45l=/9u2 +L?`^nMiNgWbs;F\ˁ?#YH?蚟0STJϳ5 ܭ](o+T5)xۼGxiSt׉K]Q(a߄k?>|-ӎn:]S"td6ɱs&l.vfT8Igw:6^t˅W[ӮyweIk{stfh"W}{/z~d{ڛROl}29͋?j{ε+y}gNM!K2}O8_ld|4q}ɭ27ϑDŽ:ϻ͚/m~ӫs\/bq^דKF fV= >jkt*Z3كT +n,i:Musʝ]-qan,6Gh~LZB'Ek׷e|쿙,kl|eg;|şjlg[^Aʂ];'x~llؽճHH:OP?ty߉/6V߻Ơr=wڃO1Mojț+xnYk7t.O/dg LWmv>F]&|7ڽ +Ǯudlb|jlD3UwjUlflxg3ʭOZ۠G/٥Sߺ_yc\3fKO~RJ^}"=.KxbKU!ooa?_veFϚ-BOLv3b#'iy+e7]o-iHQc%nEdÛ';%:9]6io1>Q78 ^sWI-E+yW3پkvb+/p?y;(doxYfZ_IȜ9{_V4eS^g7n/~"ӝʬԘoIp9ɭ-;J b8٥xe냵m)Δ,:5] +2v>v )ɚ}}5fi; =~rwǷ˫w6ѪyK-"35+Zwnk#ቯXMQuEj ϏW#EXvO?K^ei/`vYNG +nw\x_` 6U?#_h̭;K`j>xLhEPɶYYOμM +UwڶT+zN=U킟51KthU-^&u8pwH.98UWYs{^GZ{'_w|:f.vO* qwbCN@!n. ˖v4KfjK$ucw޹[?SI_Ž|`{4Sms$GЯ3.zD۶_\ғ8ۙru{i|o8'k׎B^MS'/ݝw책\6I97s]{TjrӴضoz::7EwnyXHoXGJī. c d>\]AHvֿI}ٯ ,NanŘPU{޴U,*5[1?#1SrJK@Rl^eάZl[ +/[R]'[[GqSIDۂܥ8n7wOQCEA&D-7/۳@CP5fC2.lgwADn;RO9XHOϹWFBw:q.NN)^g`opgޝ 4/mW;RV|fQּUEEmfy5<0T|r1U X6g UC|پ~S.ts™2^weeh6wO+n/@si9&N3Qaܽ*mG"U2;#k_HQ繑{!"NEm J08:mRI+0뗯RRX;Zcw,,޶t*ր!>x& 2($h)`p{ꪖXX{?*?ryw9qNjzn~9􆴏gY|\w昀dç>?9o'9TٟY`fa[WΞzwKZ..}>߹#VӳDݯKr}uOtkBS"e%8u}n~U=hX;N.HzyҌg.U%wwGv86v%{m=Zr=7u㎭vk{h>V옪99ͷg:q!6],$pᘸH,ѭg-syro#;:>(3^XQ{ 'v7ݫ?{<)gu[tМe;Y W#6юu\ +z<czέw6Kg|&/}&M_۱]Y|kWV{篱cy <K&wP{{Cn툼Z}q\#W0hz_og${9V5؟Ta a\tS>-Iz[»#rډ7&M/$F@4P[gKÖe,/|S+B{Q;{rf{ɳjʭ-+_4Ԋu3Mj_|qvH)=޹|!lY $<`2fX}hحos7:9*tRU~ſ25ҧ\|i57Wl]f>ԣ^ex򳫛r3 +^sI f--N?˼w\oM\J627>onb0IDžO=2ӵyCW-xc Wi?jn[uIM%AJBs%rR:wGږ'ܿ) J 7dܴnU(LL.v[9ZRa^׽fq}e]zl#[2O]0GwƱr5)^n(J3y`2ŷ[֏+ +vYU`AѶ3'?}1YqAl7Un.cy5xIiߵz}3`7m.oOeClKZv?R[l*g&4Vʯnfz8Lcuw͹qL{GEn%GOoѱFs34ҟUڮ<^7C] g޿}mR5.kd!uJ+ҟY0{KoPӒNSZ5_+CHsDn[~樷O^\&klZTz呧3|PVu.w \votgwOԝVZu'.9/biKWIg OzVpSb-|\>_۠ җZ*?˔g{K< /Όd~i'aJaƙU%ʳXU\FRs]Xo)ΐbmDAKLXE[9lx|=wt%.̾ƽ.11ܽ+NmS񹯍g +~'᫂Y{ISۅLK^(YtTKlbKVιxˋ=,n٫9|]6<6c>)mԟ{Jk4wz\mkOC*f>{#ӊK/ytE6$gRc>"W:[k:]޻?wd\f m(sߙ|!q]&1)Mpg-cz*wY-gG7՚춿l].-w>~⋌:;. +^#?6ǎU3 1zz?s%m}4c]Kn-I%O)485ހy~PN}&̫Y_hi$hYԺ~^Uaם_e lHms/]`k^E=o{~7S^5qk?ը=ۯog 8}ZgGФumtutb++/)-޸Wӏ) +[ʉ#6<bc9*$Hg\' o2]tIށs;ץ~ +"rB^/wJ##/4**_>m2oq^vN,iwBcnMUӖN[?Ny)2mΝ3>+9nwdi{"_>)(Y.|`V"K>4=XsKEeʍj7I+Q9oogR$s{o/|ӊW!CKڽ5=Iˮ?r> +U*rwZ^xӪ浩[V8Go c8gZ+Vy8b0rf:;m3v3^:'ggcfޜ9O'iX>YGk州ڟ 屬w~=ٿ3ӏ. + XgBY[o (?%aBlk. &/_;ZaYGY։ʗ4bO,a8\7ͯV^hQPPq_??̘ ۦ\;'\~iz?7xh5yv?M:ax'+o9<81[a313~+_hwe +SΛ%p~˒7_^~ q33'7Zn8_W[˟7\,$5өYB_*3eLj%XrBnW[={*H{QfQ7TEjgX^^!\p3iKm`߭,7,2,\6MDjugLhmsĖ*S`tM뉳Smn^Dq\)?7csG3/[>q +m1b3Ge*闃m{YG}7y;L=v-('tF|+C!Imމ'}>wlnL}B-6tρ~s*}Z+v􌨅+XnLͣX|}S>/b֟rGrB۝2g~GF~~F3BB5w[m](IhZ8~=W+^Vn)$an/C9*KESjѧwtn%}|c&k?vz/GL'kș4[7E5G0㫯[(E_b3E?j}w@NӢot[9*ᕅj^Mܖ|%'B֞t$3'ceE]EPtiV֫?OyY_tm9~Ao`{_>6 +]P_T}k8ߝ9rZJc1ɵ?C +>˸Řx3g)RΏ\rn J_+/j]xKE33ڴ^ +5lY +L0&ڊ.>VpE&O-q@i}R\ +wLV +%<65 q,TQi-瞯p>dk—1M]&_kIT_m ={+zӥb%37K45O>3%'GnqXuW4E *'ɱ^US^o3b4s>nܱ+)3íDު2Nt_5Y˲4x-|ց\B+DO̵q̳Cym6m8~clY} + 6/*hnK!Y?YZ5QY+F޹+v:T3yJ:!̜ knϑKR)ٯccB*,=9U^?J5x0ܜ:qtVO`q$T9yص~u=wޒV 2LyMV? 7mχ+\R9B$9xWZ ~zP2A'{`:W᰸l{,mn|zIG9L;?[eVte Wk*̿Or-y6y5?wN2+{7sݴ,ok2Y+q;3cKЋ6IjDؖz?7NT* mڹsyo߫6:_<$ҽŲVD֖qN䳘l8oKT"M+q<ëftW1-ez#T +fվdSswf8ML ~nYW5Las?>{Iy"s[&ڿ~Lٯ~ c{jN]-O/u~*۟JKv}r45hA{ OyHVe~8SBHyG6NNy)㺿-n}Syɳ5gx`8lȭXXέv՛ +-^?ޚ߿S ~Xlr+&p$9#w3iE@K֜w1木f+؟unką'o6d`|G*qOfi>T}'?$r*,uIW+|Qr Y]Yw.XhjTrQXԙle=r䥌Քtda'FKZڵv o~[~oʎ7T=a:9VN6".ܫVML׼?zhx$;7L[o<9g]w+Nvʚ}ޭ%(xk3胳ҏa\Iڐ=ھw(j&C!Uw +7ΫNv6Mz/D(obo=9Ϳ?O.r~ +lݷ\0q()Eh@}9> ]p݂7W^k|W6F(}1铹ʏ4]b!M녗;[g}M޸2Q7[4wKc;-:t%h_['Y>s3Fm&|ݓֹk~]1+<񺮿yLwq0Vt?Wi=w'V_Zgs ĻUs,=w~ߺ0N=-cgoӄWtB֏uGx.y9CAѷV[.=O#H:&ҜMۍg9\VzUZ3U~IY?37b?m:(taW)m?f?,LL]^|B ۇɹn.T1g}7na)?= 1UjwV8 JLfc\ڕ'4^侁тB_.f޸#duN,E#p2G;^˶#k~{>ỏ\_U ,YWiJ? ]WͼZH6|f~}eS-(cb\+TogO]t%<ͭǻdEYts^UW>ɽ<Ё㡮O#"u0?ەWrgp+4ۯ5z cұ ΍=̱u؛&+N>V͚m+L[ɶu:S9sn`H|ƓF僵kS<Ѥeb,Bf_govYXq5k*zZ9asKьrSt>^`{,OzYoڏ첖wrZ^7N~sTUBSNʕ;VoPKV1߳zMU+s]}Eݯ\xas;9{8#SUeS^HHl|UpP삢{:dޱˉCQ#OɡS8nϘy[=1].󧡠#CHnb²9[gQERGc N<$h]Vo&nw +էN5|\e MX_pG^gdH<\1Yy9V,eRkK [Շ'ʹWBUe:ڹ&6gKbNTu+AG ߧww~Ν'Ie,!oVwdzx VOr|cGAԼi:m[VW˕*"<{tZվOg ʪP )R˵+z+^8\[)Ǭ?8VW;Bܮa7ge /Ǣ٢>:ΑW/fo81 q)2sC*ٗ|?m%9OZd?i_HՌOظ 8\Eou;j1OW2fM>Ɣya}vd~Rꈈ),pzʍ\we},8=Tџu}P7mpa.U\7wH9au''zx}ߎGUce%ZiTeeA[{zF&^֕mK~*-䥇9e;0ik&ޮ&x㤼 FF?/h8{rBD;9y Tv_8lR%5fS7sb[$..ں[[cSm Ԙ^+nso;˞$^qQVۍIv̨vMغX--8h*o0)E;r1-]Y~ʗIYz2v ӯrY11ٜ`kYy?)W2pפ}X>T*?5tsuL};b+v>uϪ+_=wٞFKznu4h9TwV]wn D$U΋iDi$Kynټ]ur;o_:Kz:OLpx+㟣ﱆ. n?(wEqf_MU&,*Z-TڿCl~_sK3l^]72э +q[͊7tJkv*ɳ/TBʾ=숝gt6ǩ͵'d?=6$>ͦqˋU[=o϶sRNE׳a0|sKwؼ 59Ϫ}p%׷>6Y-m-sUO` x//mqsZ|JhGިuR2?vI%Kʼn$Y4?4z *9'{$FeNKT; gӮ:B\eO, 7i01~qU@T[?Ae?{w*Iw}O̙vqplڼýd^X/~j*>)G_I-wxwWr{>.ou?z{"&Kͷb^Sw/{RǞ:]hzWU|O3=]nPxYڝLhl?q啜wIl-lEM l*@g-;m-ev|/˥с]JJN?9(ﵭDenmnz'uN26V:5I18a\o 9oGӵ"In椀צIv͛{S]ͥ+.`JQ\;6K=UHFNxAIs4i:V//'~MwkN[uuW;l :IulhEZۺ6Qs;-</:yiæ/;8eVF UO`ywv4χi) ת6ְoD䥋C>w>g(/ O$~V(eo +Ռy/0s螈ȉ/>.`?7zޞJOu?MvVxhif"ݷ][&k=-}Yze&5[i%+qUecbMŲ7D/_S +Yqb +est)x*~Ԫvʻw + J1gJ\l2ub}34ڛprrMί>|VDD늨??.rjkUo~qb+7q?*iE +k&J t^oцʬ<噭ƫvNMasBk8i<G--gJtdN2!s[RoDL5/a4cWfiLd䁥yjmqgfIX>*pW0mRM;fl)ۢ&"a]Q/~䬟P߶뺒XWufz|.YnGFMySMno]qO{޷ښ<,n[M'Ly}QN_#I"LwO6gus7٩'\ c)mՋ..sb^w W\X j?זp[}>;xUHG+q:[籤 OWzBcآE_Bu^vs:Ń{2VU$[,Y+2]=y޵g:.9*ݓMݛ3 +H؛tw9㡁G.mҿ=UW%fYzd˄]wڦaƦ|?-00ЧEN.Z6jz량o.-UV rέe{dg#Ϝ.k$O]"Tš9[/}/f1~3>v-TֽI?,J4Ы[M`?o'ɞݲJtI=I<3q~/atA2)?3hnKjfO?hLVYwznt7_ xdMM~ݣM=6G_M=|w ܏)wZxӍs?K9og@IW\c_rퟛi|j6mA8qS\K|k[e~c T׭/$l+ R{V]#bM_(հi :VwjʔBK>wIeS19H~]q5#3dK2?z벾1;єT̼U][]˷QU_/R{Ŗt58D&oic;(i%~٣R_քc6s?{"72qմ7DӦ3wHO&l;ab=NZߟ64<>95ָ3NJwWz|g~>Y0eGR-gH`}ueÓ>KyHʞE%Mҹ"m(/~W׽ʂwL3>y%ãʮxZ7,ņ˿Orŕ"p8_uN{l\|fyM*-gz8%oWs8_-W7Kߠg{06wg/Zms9~̌hs[뱕 f2Iu,[Pњ,K,_D +jrG3ueD؆$9Il2yoרot8iOIvOOϾ'=S#~5@G~8p\'Rx^RuXΙ3mMweAkHwZiu%ўG[z Koەts&l&ɮ^ghRٵWM:iΟGb:[,*h9qe}faq6aF^³s9g&}w NiN6nYǰzM}^va5X?y-39e3mh*3cKG#xV=ּꙀT]}7uF Ki]?UDŽ*R4Y[5xֵgǞK\J`1Msۖ'J6٩NzVYo8-;nwTPc鉻.5jGc.'fN2f_Lڢ̵kBn7_ݑxE^u6K2rۯcaW4U&>aV?[~ポ}JrӖTdg.ZK4^Uj:%ΏHN <=kSY%e/= +b?[Af'fzlV~?eW$lpE hy_Gd|OSwvS~#M7YqHQVot_m\SWO%[Iïfm* v0샒F]|̎Guf9`Ii[^~9z=lPB121VmRuͿYkmL5ޗ5,9VNy H6U/涏;"[= .p0e=,E?|c͋_hB^ĩ//y㳗aBӺw(0e(:L>^ *ܴ쥑^ +~/4 ڵ*;f7wNk +^ͲDwV]׊ev>}L3-L^2mwx~oN $vr>9R:]\󼥶TŘ4t O5y$myg[O~IWg|(wK]t<-wk,rԃ-KҦב;AoևsE,ˋ1ƽ10v^IW +_b1 +vNG#T5mꁳF/f}9~{z_Ehj\M@OF,']NYuUl4"O>=^o^U[[=9:'g~kޏ'̈%I3f$жY>c&;c2?&*kr2.rؾzxj$ߞc[D>8*\Rn]*ąw~ _:NE]ߏ$̤h-ߖt\X}#jVpњ*!Y f>d٧I][+Xeb*[.~H{+NYK^t#y/ ] V,ݤ|zV3;fWMM^v)t}?N+p:?IELלN. ݘYP- +k !xe3ӶU=olv=oF|+l 0OR + LG{]_}7*u^/7\ )Wp[8[)4GeÕoEUyq xoTC#n\[ L/$Io3}eCgupZdEҙ/7Yles9z'󅄖},_sߐq'7WGsm_>F`1}STj'^70eޕxs.ߥwև~_aw9g'?plWlOPf턃ܯlryё[U7\礝Ɲ3<dTGrSy&=(j-zQ{ucMR|+Ap;'A̶MY+39iꪩs9odz6Sij V3 oȟjRDrIO,Xo09ȠXٗqR/2sY7x+w;n-9mνekm/}gk|pvvY/;z{vse1kGܽgYЪhv}zqvTkʸ|쓲`To9ayR`ˈE o;bǾs>YyڨˬU~:&vnUWxǧk<2k+J>-i`{gUhߣ>j/Vgեmt/FguOECfY\|}+zrn\rSKmag,y, 7TcѲ-?;/O؅ <ǯ|b;&y\Z}ֹl-{7A63qQ㿲xvqyMck[óT-_aX{W"s?%ӓ*U|Y_ݔ(!ϡvާG^|X\zM/ yZ&*aV>gSR[m7=ǎ +}$Q]61QWC5E7X>D6=mG/vq1&r_yby)سe +,~2uzdoCbbG>Yȋ.d{UiX\f" #MZdن&c[Wb9 ܧ_euPJ9s7Yg˹J;y1W4COO0q9 :N?FIa̚uu~gW KZ+":u庚ü_ڼ1)H@{{U:=[s\mڞp!暮fޟ,1)mJ[^E7a~RֶWmZ *har"\SE󁔜}OKܛ߮/ym?^^[seԢrg5~by;gۗ| +vk ȶʎ9mwkמp2[8w襅<[[X_] 7%n5;gZwdYUVa]'3U//_ZWF6Kkf6[]XƖpub~s̋}/zωjۚ9ʦ\} 󒟭5Flϗ?!8.ۼ^zJ@xǩ >=o|F{qM3m]Nfԝ:q?X\(՟2̥*6;2 e(0gB;Wzw*M~:W{ߊ7W,ZrÿS&*^wVA~I%ʭo1>__p?S})bmn\7) N:6b\#7$ܼzfECU5/"=pw2kfռ荺ʏܞ- vДmGow= ~_1ob-66OTo_xehsJs=_aӵ(_߹ߢnIG$8 hdmSvBj5 +Xly ߼_a:R?3d_VJlu·Ȑ[w^>e +uy;*YǜK ! r'kW8eе +|+?%фnz )N>/oZaݫq#b+*&iim Se.+}7˧$Md]oKm,lMLy^7xdc F-Oj1)$xMյM>|<$dus;1lcXl{,-cvTϕf]c:Ĝkp);]mɣ7Y@JLucYMր6ozo{꧕D?K};t^T4YͷSK68(ao#Ӧ?Ljl/92ͷgs3L8:͕=s]S\m۴l3=4|MD"L_MUWtkXik9 7'q{_w:;xsRK9=٢`}w2$ڌNg +&'7TNo9^ex <_}qs+n<-'Gҗj s,[sPuxV+OWd%^jbuَ? +c1o zw^J1#Da-\_79u:k:_K[^2fMܐνL G~dy`L 1rB[sf,R^5nbۭZ<r.? 䄄s+ut.sⷶb> Tksún&Dcf?UUڔ=_ܖF׼5Jܿ4wzXf&W%F8-Sf|n5qէXQhTo斒QsQg׀mVZ]odzO5;QjҺę~X_|~0sʁ|:,fEb'T%&X + wIwIN_+`uR*մX69n%4103g8휾m⒳˵=i^oVqX>0O?4!Y +Q^Ҷi{lQG듭8Y;Ӗ7ÖIuy +:{ᛃӏn͟7htíS++>iڼ2vۼ*9+*S[xi.7.LoL?u7gu{WemPǶ]eN] +04f|WTd/~y.cnZ;1Jy6pɀ ̧;mfZ)[v%\!Z߾xΉwx&Z`礽 k;li6.kU( =tE +B'X25nJO}_PCY:Tl{9w +W'yYi-{Of|vI,vɦhUokdzlWrM7i{tI$9^~=v~e{-Wá0<İ&óWTUxyӎlXy`ƻJw}QݥxBl!R lܚT|r U6F3;cpoat`p#a:IywoS:](]`} ?Ͻ(SHAݬVm'Ϛ^oʜ?jo4 '~KOnWl]8tz=^2_\NMeNgEޞQ/߳Ғ;5 5_œv[k`t?_QW~Xo49 kϨoy 0RAC|֯nwݢ{r`m6s,>O `ҍ;j j>{_sCWU˺S ,N8U1wߋr)k_*{twDo8ܷԇ3zX|;kozv3&g3W`5څ&:lƳ~۞wou/Vˆ>Ze>m'3Z~ ZZ'ګ^N/ZxPCءˮG:tZd9|£vCDz]iA);3ӹvԶM/{-SX 9;,N8S9x +khO꺘"v-Utv}UeY8c_W{g ѩ.xf ^O6NƤ^͊{:RiMt[{&)2[{9WkfOm8޻(4pýUWv~wi}yC#O%j&-Nٴ [4w[׿8]e&4d딳_nu yjgٝv*_ ~H-(x/{NŎG>^=acrmo縘ּqx1o*0ioCl6/_tSdž7p?43[b?E3˧ ?PYL_j*gT~ڇ>/rWrǖ髼ݲb])Km&ޱ.f=KDV|3nM-?MT_'UNJǛ`կV;ն$|GU۽설W7L|Y1[s[=\rVd'q,xqtT?+7߻QeeWݐ'G$$mНGN4y2GE[,Kp%V;zqǖF_V>z͖9 rul\@ D ]Gc?ELo~S"_5V=h|6o{dVI'dwwl#~Zw!GI{3[ۼ<ޥk }2;}|Y=[MڥFLR_}7,T@ IzIkCLTM1kQ+4֞G!y1_/ʹETȱl{We?|P>Dw٬7龞"%}_\}e6;m~btۍs+ft=.,Dž_r IU79L4{֯s% +~g_3v.g/VŞآĔ7f8q*3[ba6t:k +sRq!+RWԲFoG$t< [h|-brH- Y%kv:YrT*_izm+.^^a21yUWK+xZ&1ҡw.l?!swV}QBCe9E{yIМr~C'.<*擂],~(|HЏ3C_Nu,0y ^V+|os.?tfvEL<q٥). +*k}"˧/hzݽo#_NXe@J5_V/07w6DY$tZGؾW?ɚ13+Ig%-km}2*OC8n;fpZccP3eK'$ެ9r?I=+z*ŗ m$槁$,)>Jz:/I +s).KW4}tA=w +—.kiџN21՟> ^{-0d`kxuշl 97:uI i6 'i|D^GRd_zyLj\P6˳i3[f+8}VnlH_쏬ܣz s*pšKvFfQ b1W7]NM'gIuRZ|D~}W{N:-;O왨2/gZrzM% +!Sg={gzYO)OP葇Wsz9}VrɻeߴtT-^i.߭X֦]o^b%7,g;/sӭm⒞j'kੰ֜wEoP:~4hT^Ui/h7-(yC'ġ$۹?/tMb;\a +n)Ԕ~,Fi,W,7o 7ǤI)ov}OmB(Ϫ=_mpXȔ[2NsíY?Z%R͕+3Rʎ[^{IJǺuJo>\ft}ZWvΔi{ƭǪWglQ1qqYJΎ8Q'nrs榕G>ZY*P!<ڦlO3cCyՄ';Q[M.ڌ/^|@LIyS,oyp1*r|3MWIPJ6nw!ou}+CM7f\sD'OW|wI9I/&rL8Kڎ!??=^$NQx/(0:%= 3;bEMZ^nsOySgM#cnJ$?'-?u7M?\a ՚#E>Nj٠>\<۰D'ZabUV},v?,ƥh#󖛜9m_iWloh a=MhX{b$v/ɤyu<|^, bH8ZKo]6)!iwƘEVO~Q]p=K䎯;]:>+g?O)Rwaͦ>?/I$7f.5ک +8=P2]rklXaׇº9]iyr-_{BsriM1e*:m^ԘoVwsCZ͹~.yNPG'ܺdcRE.=۳BKMQ_Xv%O/^Ʒ?wpׅW7.ϳv<|{oܵ,-f\ȘI`ig=X6QX'%O]o^˪Uj B +6q߲𖟍)7QGmҙ.:=N^㒒6QaםZ:!7Vt.Wy/(4_t.we=rxX[a;qL}5婝۹3{g(\XyLa/^<{i[4-N*)||Yyil[zLpeƲB}oM yޱ2zlۼU~_ .-[:!z^oWwÒ7k|:^"#)en~z7yۜ+/9&aSQc|b3? +՘m'{j7u V?N~\Rz.f܃ⅲ?q+<䝓t_좹'..3M<{5m$2]RQ㓻n9X=6yWKG_,/HYKx/m`Zaj(kY{?soKh[!(<$kN% :_3Sk?1u-v9Il +߬" ٝ_Қ<({f3LVx6)6jQHnKwŝj{RѴ'Il/_ﮑt_0{>zS21~OnU} e2ۧzJpկlMr]IPzzV/6p]po />xuf7Gmɳ32bq\Sn/-Xs4itƟ_ClLO8Z\xr*{W+`|lԖ/a[xݭqX}8K ;nbynOIwߤi]ivqm7+㼗3sT#nǗupNz23V$2(E<+g.Qb>Ʃ@UGaѫ}7XMoTӠ2(pBF9Q|F1mǂ-\ʼay+x[M1NF W^.fO]>dq>iߵ{lJxq?Ą/UeLxځ!to/oAFUb}67ʯu+ ]XMv7 tr+Uݙ3ҝiўY/T;npu{'3p ^xS]GþWF.0јWSA{;V瞿M)Ql߳Cu~^xP_KӊcEi0q0+'(~p k Eu4ynzVۻN7+ogQGf65E6TdYݛe;ؿ7qWq޵wݴV'mepD5 H=3hPPy#He1E"=YsP^O;.y_LZ٪6J+ \S y 1?6v֖qܷ|q7 Y:߹kZƖŦ? ¶4q-PJj-qeqS'|׷4?5ף7Y^Ȱ̗4Z7NMNƴEV[~?y'9笙v5 7/0pvIJ{Rl*;6, Cױmw@4!;'x} uX+P鳻kwƓJ~O:~<~I3/͙|鷫'~̫Tg99XM'\{8{m+5748 $wfPZN旪gvixڧIRoO*%[OH;j-s*'>^,^x[޽Ii"J}|N;:Jf&׵z]4e/&9E- f>Dy;?߲R̎3>~fܓ۞$!KJTyu1jyFs<#{#$r m% +ˍ+vi:_5+fGp.z폿 w]U%8ۍ;C# ϗ/Ʌ)s.-|((putO5/ڣ*SUΛDY6/Yk@PN-Ƕ4#En$jig}UBgW_FS~̖ g׮;ߚzѵJ O\:6멧tD;%'zlr" &.oN乺-Cn34_sf0{Gԃ>wgלLf=*вcұLS қ9ss:eC㮝z? 骗?~q-nK-48j^yGł=|!%G|_/s$_~ݙk1ܶ\˄5D}szS.Th|g_K>u/)_-FAU[o>5|Z" Nуsos.idm Wa;xi۴NMZjpM|ӪƖj.ΫY=o/4rmzQN>vwyuǪS;lg/b/TXTu:[Bߺ';hn )aMڕ g +*y+8X۶.p"[n7Irks֚dЯBZeG+d.X|mv4n2[R(o"in ['5EG o^{P)˾K[ТM"NV]2qcGyxʳҶ9s~2ȴڼgqsl>d'K~k 嘓M꿢pS9W'~~@wH\;7 +.gRa򛸣r~ˤ }p н_9\X{}]Tl􉷢[u\7w5r7.x2a7֙ U+D}=셨7>>M{ꦜQSXax|̫ԋT MBOͧwgZVI:o&2PN0fWwmGMi` +v dޓ=Lݙtw}֯5[?5kuϣ٤`&-wf>ڦ"<-)oo;]u._.Z*:EAϼI䰓xڮ9w~.qɑw]jy+%n^ڱSm[mk{^=>Kpj.z\dMeJFjCpJ W]Ыj;AO\gw{ T`Ǻa-wۻj;]Q?mܣſr;1rNw9fe&&a=\nڶT+vMݯm=`}A>:IOHږG]~׊;u*95= NnUy4מ{Bc/_g"Wクn=x/z?[/|9ٯMgϨbU{ͽ>-lF/{n'-FB.]''7n:xϯC[|fRԠ(6&?]8yz|I?9:qu1 \4kk IdSE}$#߸띐UM۴r[f/j0+Ia{DْG7OfzGg>?hbrcs`/`}MJl0[Wl1+s.}ۅ4k:zN]؍kӵ7yf9w㚄ޜ饟%Weޭ =\`έOc3ڼњKE&x1UȧK@Ajε;?7,|mTiÂi16佾U9g6x/nsF[fFX\]wg𶼇 +E&ޒqvy_'sVSosuDN[%3;5͙[-&vP]_wDrXCx*]}_g%N1YwsGmSߜVW\u=˦l#&7!F +fC ߤPԠ)Ka˭-y3ijͩ\˧/ "sᇽ=ozogl3'dV;\nwWVU_n~ ;=ryXl%=mWBv.}ēE +ZmʹNrñ+/ۗ÷inc "?I+Xwng~j^Wț:6\qŵ⌳g(=_wGʈ맺lDOUS6ԏPtoM;#YӼL_2Z—_ê)/}eYf;q +{bV-,;<ɏK06O͑Jss[=Vn8W {~{)e=ƷrZ'W\:u-}?km[kO(_g6:fqӗ+ķ^o;&Y,󳣟_+z/ꣶ +ଟ[?2cΫ/j&Dw-O]uyyjyS2{ìvz_H le{CUNJ4}1/8Gi<gBѺo,>1)]j\AϖU.Kl=ɴ=6UOl\BC딀>v[K2 *kbO^n{(r~y*E{9]\(8iۿ_>d`&׭87IrN3CFľog%AO%΅DΛs|Y^G]gKSoO_6}d_$,Q²/ +vXԲ70eu*أ\,U{\ln"Oz{dϥ2kyJvIp1_ +Lxwi)9N#ӷ 08$@?omZs[z$kIK߮ܢz=K&v%eA1\<_]]%R #o=2O~U]ɯ_f^_t`nWLAJN՜f/mOlz瞩lpK$7fͫ9,difjƳ>;&:n3&цmLw^:IRXӚ_1ƹasfl^}3i +k ;JypL›6s7ު}Z#{dx]r +1+$&YR}tINjIzZ BXyu(V{(Kfu+Qf?M-*>-k}3<&ۤ/j:~{O7gat* ɧ0:SrEqVQͯVJNPhϗ={:zpxi8hDU=#^UH\ѽ{'vus~͵i5R}>gG+<%4&eEvn#y\&>Y{)\o尗,4i)VOΘ0QqM5FEo9kySZΧe\32=rλo, u<"κpwB'g'uf\ l{#lu>9Gpy9i8]69%׉ P+rؚ{_۵hoW`$%n~K|=?K<:;bBm|n\,o|}\1dE-Eاsޙ}q=5%쿳qj.\4cډ3}ϭ\-eYXcVl {^mxw`_w\f5Y5n̷f#Mbod[;4 TwKDo6կbUD]+Ԫ$x*H?39pKwܑ٬_Z]Qn~(yBvZG;|aѮ|͜ޟgN^K3nuS{/?wzCy%չF_{['ڔaphh[[ʗ3lQ5_yjGk?2 4nr) 1Yko# [%_ZSr%.{|6zykfaiUɰQqDW>VVԏgbDv.V?YAV7=&;[iLO-c: +.9 R*_9orN:h^o*vvӱf2#f&.NVҷUy?"}&b֗SUs<웢yL-~w?yX'T=]^!dwAGKg/p`Faqs ;gEV!r6G /V4!t3U~4pu~Β{ӺdDvM9i?.4֬ ?N:}HS'c7<-<1Qތ +xql#qm(eOy[wϏ-vϸ@ +Qn˹o2Ljuj c'~>ҿdב[V?>gzB)7٩{jCLg"y9&-e} demOUWNz4|.gBDMEڍ(Hu6?)$Yݞy3Uk5W7w|r[ɽ/?8oԓw~j.SGL':+mEUGU+Ѳ䳸d\qʍ9'J +Nޗ=U|yoyΛhxcˈE|/Co޼{_[>f4_|CI02R>Y3B\'; } ''(X3x_ mH[,ɹ)>Us#B_䂊ZMS˗|Nb뾴WlmԇЧWbHN=SO8~ii-7?Txt~53?rdA2i9H٧\{/qZnR~^Q;s8w5˾l _?-w/g +Dz}ˎo +{6x:9ݨ]MPŶM\߸Jeލ_zfeIN6oպbP钂;fB3+6+ۜ:̳]gڦЌTyR᭳yeil =5zm/< KbXLK9&‰i_r{>JSnMq֏36˴ϐ7Smuӗ<|T"y^K~v]Ʌ)ƫYZwm;T2f7q4Uepu7E?y&aUsj7ſ>|{5}ϯZl1=GPl}|ٓe|tpd^*ʚ-oTe <:͚,:kDsK?L$|r'죧d2nojij+Zv臨{M {TW-fnە{ZfemiGjΜןC߹Ov-4Z}9!40f纗s$os2?7 VzzH]O9ާ:\XK,ӝ. *gɎ8jOGn7=|1x'3?6nm '[Q[>H<}[fYm?ŗ[6^W9HǺ2wr{n8-;~Ua`Dqٸ']߻i՘?M٢lu-gJNwm N$%oŻCS^߱S-ϳ-iIRaK.z {nlNL'"|`Uooܝl^sy[wy9hD)8nՉw}.ZǖWПeYQ߅j=7C +X|kϐ Dž{M{O-cfVR1V"V\moxBK0eZw=x""RQ9[Mr eݵr Oz^T?Rb鰦'5tT {)|fdFѳ_4T*Y60ֶY[/]]9砏˱~8׺ٴ)Pʹ^GYSWf8xVcbx}}mj7N*$_j+Է}k>uǜ>7nn役==lge. 7Ó%9E-B2k+Ùjf +pnJy7o_^W<8<'puzaz#Nykj\A49S,rgqr -rV-)O6P~z(D˅.>]?hcsONaVSQy{o 1)G[`)yvU*/Օmv87u猴9̛5iJ8OgG^=E|ai[|<$9{$\0:֧:u*xP>1 yפL)}8yVmZB}㕮N7,Znڅ"=KsﭦWEQlʏKWpN=ZjmxwoGlax9QrӪE *%4h]lveKe'dݚ w^][o799ܥˎ\VZ"zaGCBŲqvnO +vO[-?T\̓?)zLjWf<f"Nʳ3} i7ًg ٽZ+ձ//~zҪGw5}5~ŕ-Mrд쾰@5ygq j8]f1Kgxak+/UUk_&O4yo0Z fV3T?}ܩ.SOeV+hitv+\.t%gise0cVfhf=%jsͺ7脫A[?yS٦TCOjӫRK-.t=WWקj^3hj}t.fϽ̜$9b'|7hv㏸tl8,"g3*U\ѡ<7bXyt,/nRqޡ8~)Rnjb餧evUXIE殍0kMpagD/v2?0!uVI²ݏ=7|'/OZ?w +=s؟l[py>.Xg? kP,@@fGŇ{|ש0EgB4'K_g=,9jCݓ[m)Z+[}K[~k<(wf])qi̋48ǭzCo1ӄf<<;H$uO\ͱEO\Pq'uIkL73z6;[HGub˔HޣoS`xw~3p+<5ssPӛs,Ի15+yg\#''N<`zN<5o|cgy_7 [mtHʥK/:c.ɧAWj=Z?<VЧSs7N s]gᬐp^/d򫣙4_V=eQ-cvKD Ņ:,Ll4M~;wuxwW>.տݪ(ƕ)jQgӾz޺4\[|b*jZⵃOVow$>VWU%(Κ^-ZK2Nvߔp[n}quŋ\/fۿRl1oi9[t᫏Y+nۙO>u+DX ^{u+Cg:v'\p5c8].qվLU~N<7_`pE@ma#3ny4Gvuc| :-~]&egE&d":A]*["cyWV;k2&Qtcﴫ}|+lJP~c\F%u;:,sr/Yeyu6U32i/ol\iU NY꛸tX-oX}Zƥ۽f鍨㯮f)x;Xꢈ }?L̶MTԔv}N _$|*]A+_~v>jO?:g}w+W[vk|09aû5)/_S;c-˴;YjJ6կc^RΈKvdpMiϥxY vH镥sni<+ܳ&,ed1^H~N`y~VS^'tV{|%v||A!WT֞T_Y3sKfzig7T5Jy$f4}ڲo7%7qM\\$ose~>70)[aLĪN+9/:̷:a˧[6Ee/6_skbG ?-,yǝ/3wkدeSI̹JWx]R_ݒS7Oƚ6*|]o9MyQu&\27Ψ}MsھaCTyI* +}sug3k_nP\(e+/V K̶=g{q×Y%'=[qum˝w-"ƴrn͍wëL=9U˜qmM=)׍3g[#tyiל{LJ'|lo +OOX{D 5r_^z{Z)gs.gBJeoCqN>H)[zi׳#9rŷDorIꎘcoؑ_ L/Qonm;*JpT1857NJ?Y+f%j ~)N,y_p_)XC[ ћ׏㴟bڰ9I' "S~U/_иNPsZWN}Xζ9 +7nZIsjO]aDMezy]9..PtzSWê1-93#q[P'lUi/%':~3tdx|_9aBu/))5ٿ:zEM L>|]Sf?V8,tBxGBR jgb8_ya]_ŵrK-4J$cFO_/}1%n/VOO]^=Oq߆=ԏygˋgދ]y WcJY6政ʵWyK_,Il/bu~y/rpF}Ϸ[c-Htwӳqn[.c6'zv*|ie睺^+U_pX _ަͳWwEO$4ze=fڼxmV]-ZeU^|v!9ˬ?\NK42ϿXRinV鏃u+;.tbC:P%7KΏV_Z#c~2j޳S߷*O +{v0b̀ylr;,:"6nuϫ|jfߛY͗4]8?X}g&I3e7V~zG_,ue7D}|1=ԗm+j;4o}g{ӺW?i~>ѕb½=Kdڠ۱3Q&^nӿm`/&W R~mDxeDxkÒn-le8b+*.f +8I>t {|aiӵ<̏G׵wm ϢgQ{I!_ g|`(Ezds_nӷRP`ݣoK]H=xړrܵOm2Wf?aq8zWĊMAS^&z76/[BydHyKfoZ/v޵x YNRc2ŋryK-LzYrMOo$n]Pk0hFcme'jMj߯ [?vh3lfJlở65򚋺k; +~zXLNyLmR8xoKY+ٶ)u۵'- yL/BjZۧ[RYKLʺ>7?7wdvN>%ŸYhAIK_k-wf0m3ko.-'믾0EQcZ;$u?[=7V#oDvs#˩[e*,@ߚWp$m*\]~㣿k-">?cI?E+Sp얳\Ǟ}JMvR;&'ùfY}Uz{BW + x0ћ+~}l,Wɽ=|nMΤKo!~^*(HoT. +N{V{/{B'ϚfqSX§b 齧NT7t_ " +`9ǻ:o\e9꿟׸ͺכ lNe7=s^iìڍg>´9BByçfe(39ߌ3n^;qfFC-\G+ʋ5i1۹XtS +ITnggd3=Vp]ǵcFFE5w;5~JlfB\ފ|n˷vlrH}Ds.!?MOڭoO?<w\UR|ÄS/Kʽyݚ+Y^bzJ}f;k7v'lN95 lZ  \2+n:pa*VIB+ݰYvϋuw1u7>KmW9se-OJXd^Cir%I~_շmʎs3l?y/kE_\֣W.ƚ^KΑʏy5&YX~Ÿ**#轚eϟY3.hu!dש q׎/cԪ>%v}s)S8K5[S[=?8y͂[Ԙ No6{Ϟ *vE/R;.⹻=oLn㬕+8^y l+|;g1ִ֦j}2;t"%-=љ:?oLm'Xl _NX~6M3n=kQ1=gNO0_dgP0w+-3Sg+Pfj<=U/u$-JXEӕlj{.4q$9#C<;[qʗ#W^B_뽮+͎Z[q)o_j)"4gז|N;+w\" Y[w7-C[ռUVrl!j2lҲ%O 8>Tr%);RD/[^ʗ@sKr _x\Vlmd0J6/9tґt= +c^,?|;/"yX+&ImMwyzH;m_vT~ޟvcͽr/S»^mJb4q<ؒ\e.V7n;o3U Q$54 _ ;, +.mUo|T})w/mXS>w'cBDSyI+[Oo뱝x">U3-F$ғ,~ɖ=L4=WYf|^WL_f{PNBWBoX_dWຮM{K$63Iuۑ^̐u9_ +BNק7jԕX!E903)gh)CIo/8}>[|a{z{Uf>#nӭKs_q} gFn ԺEɟG<דH>nzeOpٺɪ|B&0MP`6/^ѦNMxw%t;1OYιՖq=H==cjN֧_lY)}hQr+&9Yaæ1o. u-_@|&/ouәz7.l~qXSsEgLL/)=[ jr!VùXuKʕ<>T"Βs.٪2ǿ;__RhBa ^z9*6Hvơd^(Y2_}jQuB ]|^q[mp[\tCA O$*4Kcϰ,qڻZAG;X[=$SKw0;aℝW*x JHre6&];Ntw'WZ?OBS䂻C4{?}לK *[mC~Cǘ?yȹ6x_r҇>{d،*? ےRYm{K[^klq(إ!;z*;ftq`X7z7;*_z]Vg'zYe6Vw㍛e1sTl݁ٷw{Fv9vݜzi̺`f|ӹm'eo6aݽ+JxL/е:4IƸgJH\a} []0%{ΝU]eN/V)tu_,xƏ?拞ҙiM_3󜼢:nu=ln[r'}3[l9cW뮔ӋW1fSmst{؉ jqTyjKQ_H/(#MzYCBo'83KR¶n +uv85,vzoqӧڦJdVY7ck6?C;=AgI/ĢO̳͋*]dL'N2P"={jeɗS)\SbyчUߏhNVxo}ioiΔ>ټUiQ3>|캓;\v|x؈x߁ >Ѽ22gH)r=TiY_<9kE|v5%}j|FN#/q0dWT't@39?kHeT@֞m*ssuܰLU{BŒrs0zć[ٽX53F|?|Li!r삯:Y&͸tbeۮGYk]*eɮ_oaV}W)|J;zZPۼKӌkWLӵ(ݝ N:(sUwK{Wڏ_.@QSn7x;]'>T20%E%v~VXʴʓvVKeO띬>+EnEn=ZS.{[wt| ϫ:7YXgKDTdB潭wT81 }0ϘxQHU`{DMm6#+}woouR˱aW%q)d]q2jO6;C;6*v_U81 Pe94fӇx->GRߦ_QEfƿ3-W/\˯f+黬y~ZX`~d~{ oVV7oxzͅC?4l',,+y:7g}9'ĊRU,׾Gv+˹K1lѻxcύ "5N^;:67~Y9w"OuNg{@r䱣9SLiEߝy'ԣͱ+.cobnzϺ/Τyǟ?L2'B n[x|%+eK}{hhro`m2 +Fퟣ}}wT吤9GMO +R[2ke!ۛ$eznj_&)v /*E4}u򑏫ήiKә= G]nb+ ]I՚W\-r]жvk+]y/ԅ-r{8v&3),~ -Qwqމ1785t,O0MܷvP qeBvXg~In}X\l&0YkSΩ[=[V.w>Ǣ93~~gPRvrߥ~6[_3;jlXMn36[껹bc@R +C +rTiOzpńwI%WF\aLלOC.p6L^f])^؄=?$[P"}GGڋE5\b/&|4ˤ-۸߾OW;ٿpRu׽S8 E' pө[w׹ao&R_B?y-\&j$fa岣*fzi(n<3UbwJe^ٴzU*'aqqokvNsLgLsNŽ敽/.~1$[2jer& =]:[·>/>u/W3>Ɣ=:{D?qO, +W2I=Z%#3"ԧ5㕎Ӯg-꾞l>s8ǩHP}ݬ[() o>xj*UTctoMε훶;:Τ1o_&sČl(}KO{T`ߖ'zs4<üؾۇ'z]ϒoҥuoVWul x[tٔ{ߏx7dYO&?h'e,YW onƳ5Nq>vcfγ4Sn!6mY&ag|ɮjZ0M׮ޟC;sCӬ7wgJ|gk<|mhksb=뢃sN~plB+7KfklWGʇ?-wN熉V2.m/kM-l_ûNtSͲFotU;e=Mnm;+5'I7:~ldoď6::)L6~~ܶ9 +T_\pRbqĊ6k爵/3Ǟh't~sbgW?zM7aK.O]s$klj w n u8r'.>[b%kD3n-<&\ 9>ERĽ[B3 9].wZ~uotOYk]oV8 vN_-{5l{Uq3غ}+>7=:6T}bYQx,Md{,i=`$:M;~+lVPnl^ֿɣtKL󵙞&3^S[|6e_wΗR;r 4ayc']5f\~;LϜ]PveF~?rpF{mzs$bC ^%^,.U)~ܕz]tO'վM]X{[#^^_[>{*0Ǧ ]=|78 +-ElJ߻Vݲ~p%I6B{oW0+췯 Y:ZbHWWþ]FjxӳH4u}+ԝ6dfwJi>먻MMl.*3wǓiˎ=sF u+Wm^qߝi^w>{tCW3}bM^IʨH5vJjųϏދbӎM9ðنZ~ͱ޷|/ z56U'}yR*9*%Kuϳ̛:;l;}w?{Ӆ϶̛+i"4iu/ :*5$Uiyt + +;56MݰESn>km#S=OabKϽ7(Hn{bRl^džن{t:Ď\ePu.m…?\l-yz?z +Kܨ=͹v"+\OhNu]+fn*yS[=G>kKslMƬ΅s~2pL ύAOeucZJ,puϡs~G*LC=Ǧ&m &PRwmvקs_ +sS}]铥='y؛;if8AIK>h{%CO&qx ~Gޑ:ᩑ3OuT\W3Y~},O$,~"dKȝma|khߢ0wBWQ|ގ{>vΏ޸=D£hz2W)C9S3iה +s_] dVuGSޤֽVt^~pM\gʃ &Kj=ʘ=,=TNUYQ)˴RwY;B'z??iZl~ۗ &I;Ǽ~"&yIh;F~%1:7߹3d)ϝ4?`c*\t+b++߹O59f澏Ņ=YRdIfw굗 }zN̈sA{iϬx*eL/ǿdb8ŭ4^vL?8ژyEr~U#6Y4׶F;}Ӧ}v>eȉr=?I{r5k霴p5+{:NX1}WBؔ3mf%)4giɲD]Om߿+}[}b3Q*/h֦xFϣRy_}r[]^-~hAVpzkt;pUί\9n:=J}h##lkX!%ɫҎ0O;찛 &w잾"-ͥ9<X}L$Vin6?|B?uRk^MY? udXDz7\R|ym~vKTJ\󵫵ELݫ쇓[|9b5*Z_,ɧ`U\k+:'vo77Tg=GL[~NۉM晩Ҳaݵdõa/~H_{:,I1).e2α` +TY:;̧W>=3o]_MiRo_׵SרI~wݪL{/V±֫0){vX]zߖ̿=9Qmzz|ʁ u[mkg(m=rBWrslp;=}{ޱ3>^9W$RH}\G +ΘoߘlGEII-ZenS-]).@F3kTu5~%*]Ta_w'$pЃߍ,j;ybHu +VhTV/qMsbc([{9]w FUsWq9T1>#t_+>^7=5uK]F+\*6K t5+.lӌY?ia2z3 M\lLhNW;K${ZyzQ!Hm$[|:jmHq\[$hޣ:t-nIH)93>d7k&<3^^wWU\F^gfGi_%Y=OTʏ޳;Om-ٿ?LOPb&)OG<*Uu.rtx$}~i.Mg_-EBp3ԾeyU>>Xd{n;=wuiIvFW.(2ȅwm^]wPoQuR}׳͉\j'~vw7q;/g.}{D3&nVzmn"N酽-P_`s[1aVӯ?tNaZ~">aGvunyE,{%7ˆ%{,ZtwFjyWΜ"GaŸMorŹ$??;7osn͗]~ՅXդ ?eMT;QSǠ`ݷ)/Ħ(>tuWq:S?ʦ*p m/o2esl=O5E?!8pھk?$zۘ9Zm4Yn<k'ۖ]b֬W,.:jٛ>%Y2wN˧%8.]tZ9ن5†bo-U{v += ;)vnU?JD+L&hW;QxRwщ7M6Zu>lnOAߊWnsw Id5p mޗئ/抏(~q㯪BDE^lӖӊ哽h:EVA̙+n\*sg}(g탃+6d>ݸvi~Tp2Z^<4߯]uEV|7sʜƤGOdw_|sYZuD~ET|ѹo ӗM8$RuQJN;~>90}O,º3^tcIlb(Wy]B/޸l˻_{%l|4?q+Մ?-|S +WjBA-խ]O$g̪U"g|&mmy& LoNfbzGAs}y+|79(4q~ޗO#trFIbd?!W,SHYnmp+-{7nvJ37~{c7!tagmNۯ<[7p EqN_I/~irf?"5 E>mNkq 2~MRibԻ%5eRvý~?p2e-7fWvicue?n_~phY} Og3*Wٰcٽo,3ZR=_?%(Byϵ *\(T˔upoF;o*p;`^~i>A$OzAn=[3z+0.>9D|Ӿ\$.չKg>"Zh"uC^rɭs'p^>×i6﻾N=K]+3w0˜`ǻ~~/2&ܖ.B{Ru|Z|lUuF"~[?@=:72W-,u5eaΊ;fz4Q2|G{O)͔~q|C÷~aV݅SV޽__wik4צO Z$L0'g? bRњut&O}ڇʯ\ kSbpLm;ջ+bLX B/paBib,GܾgWoa>{>W#?E-^cb*{՚?M;՛/S"Jy&_?]UNHƥ7ZVXhF(U4yqBYϧ}u٦hDfg:vh2]iu&PGݎ~]5l. $2|2:k|{b{2v^9fU{?-,az}FLhwRw9 +'jsR?njZu-nodSn8{?Ո\kzo>[rCx˗w\YC"3f\/-a &{ݖ}'o>WZvvJN% n͟fQ3 _ݭxObvIϺ[ԝQt ˶ =]HwMW]k^s`jgG O&y;lyÙ **Ur,reь$~f6nACۏ0$imQD?B&? 5_߿s9r'9Lz{R5%VGv*|8b']6߹sA^t[lrk7^3q]zDjuCg/krmM[ݕfskdX^;eam\+j[^9q."aRklٳ{;?i%üwu}dn%fldtJ켸Z6BV.X,se=Kǭ&k~xlYQS5U^u_%x60O^&GlYq$IΞd39e9tvˡJ_bjʪe8%)]re獅'\c\h@ϻ젞~`-yӻa'O;׊O?/zsO'~ɦEwՔ:on_@VyNm+/m5O}[WgaeCk~[f?j4S? u73FMqbDגb_pXV:r&]"2/uTR0l\8cZf;?c_,AOrZr.sE`U k.KW6mkQ*"aMlֽu\nw/fb̜'qCjIEo3EO훞5>o+OfZ'Ʀ%kMUJ7R +w45g=mWNj_N:rS[XJNWN>Y;UkgI}{mo?+<5.Uﺻ~UWڍ_+ >qeβLg<,Uve%c[$d]xy[W}S84t]ة*tjFW}ks ],t2Q,c":ED)/_]?oB79n^˗zbT}g$\">+Xq_ޛtjgm괬QoxBۨ+U=` ۹ݣE?ٕV/qZ~C'CJ+,=+Jg-OG[U{&kMN NչxyQד[&J J{#z"7Ac'7K1Mٵ&^Oc:i}1Xt'wLarӞdy3#4E2#4{onRP5EW9++g\sNTxw6]-<\X>H +ov,7tz.>M7R7kvz&)* m~̚qr^Xqjl$S|',ix~.7؍4\"o./anv[}p?2ԪI-<Ӓ;wLȳiߛU-ҘV]]K?~߳!V}]^oOZ{Ig󦹵OtX3fVmqI?h*{W-gM׻x۶U)jZd7Hgtd|/\]Wc N/w;&zK wNO_ܮSwŋ~ә2ՊY[sι:KVtuZ6J:fnioa,2=*\Jjd^Cܱ; +,,M<{zTRţ޶泈|# eۗU3&hpGN=Z2<ϒ+680U/A?뽸X%( [8%aeuA'z\ZDhlrKךpG9g[y>IomO3} YA%VNk +>Yqª. +?gmoXGijV̫ptHXUü2e?Hݾ9~k-e|Ȗ$Z9!l֓~| r4*~EO3Y?Nǫg/J6"09ԭ9l#fM%}Q=^qV^{py9N.mdڢ?OW-q=%CӶ1KƴMe=W"LQ ,i훹G{ҋ̞It5v.{Vg%}D>[u[^rmw62{:0&[`⊵߮xIvmI <ĬO^kEw9x6@ᓊOrWdc=v,gV>*nsYnS`ɭϼmgӯyvungĂ]llM.cçwZm}YWOk|y!J؆oL/URkvW\Y>zO6)+5'uR\ήe]xޏ'Lb&-|P{ Tf =dژxygɌiw$?aZ}Ra|f_8#eݭ֝NoMv|''#&0? ϼ;ijϋܦ=s tt%kZI[mźEM;gp+͸iSȻs&{ھ3|%O_J&<+B6r]X۲l✿ڹ>HuE: m%mٗPW&2|ڞW[tԻOk\IJ)ooyŹjgKj̿)]o s:S(oE %b=2zU:XQ:O&mMs>!c-+Ciqiɛnk>^L˻Xkb{ nY7ϗ|>v~ͶY3f 1)1δ;m3~Tk.q֫=nşdgx-`>Ǧm.|+N$m-x0w9[t96aERnuK@苞ݛ +L*;߲1:~Nsn]-pu}O;YZd.~_Ŵ,Fתiɵ\}mZOuNJ'l)?Ðt6S]سJo漇Z]^螶йs_-g=s>[cz]ǿ979gb[藘wS͖Pow&&y{iYݼ'O_OREivM8žxUntﱟj䈥k;*68f0ΝpeNd1rņy֒oZ-ϋani. ɗ6sDU}aj5:f.庅9/ xnxCz'_~Y8A ^RؔSƳ=b&;]Q]W,o)T3t4)^R\gwvFU̷pL}^^o-+iU 6S&L:-.s]hw\CmzMu;>o~Q;7ְ_Y|F]g.|vhQgf:\a'YmmO_bqayޔ|ur %ؔs&omw[YxPG`~< +sed$"艢vE/ i\}O6B :W0?/_wm^Soߧڒ7VO|`,ZMɵ"+d~Z)({I3B 'Ll8<&ݽt9B [|?rI^,U7 _=գ'3U Kg_]:nK#s k_=Z̖MWע=JUa2fg"/ rd&`"'};tʢB~?ژzd>o޽rG =wk9#or'f>?SN4 + D'.hsv=_Vo_k*.s4RJ#7Ɖw<8|Hpå,"p^xF-zNAז;.þgNM)W5m=tGI/s$SAgkbqχk DV*@ʫɂBYiZ)r]ǜ]$'kϟ3_s2yþG_,XX/Sn+v:g}l}[C.I]i{jza'\0-y_XK|;𮔯_l]KL5zp$$?B7oa7eaMUrfura4sN>)vkY[xY_2Yxʍf=t+ 򿺳flex{ˇ3f~v^K_mj0cj^TK9.?/s)!>w}8s~ٜZWeg/+>(O_gWE,N;?,˖:~mܲ+cw|{ڊX]sECfxμX\uIy; +fx9jӿ/yה6, OI7uθ˓8N9sb˫~8MtZ2~_K^*j˿ZUZW2w40 φ +on+ko;amΔ^6z߭^Дپ\ˍJu]ຓ&{g<vqK+r$ۼ,zveN(dl;zəI눼RgV}kW3:nL,ٕ-CN;탋}uHnGSr7Yn2KTY}l,d\m+jo0[v;vt-<*c-G(g3D=ZGL:7սT>¡/|[߉MڽaB "Vk|]l.Ⱥ^(]wQ3/-~Egum^ѼNIs +j1Rog"tSYrגG9:Gs'hTc5E-Y{~ȼ{oi#KR9@w;*U>?sj +RVxWoTǿp#U_L}ݳO :[wOy)}#گ֟78]KHㆯ3}ޝcd)=oWfz1J flYO߾⪷wS| auՉSN(Әh${WXZgip=Kpy WݕX;_xp ~ Ȭ<*73>Noaxe[qUA)]r5L۽;mX2ݶ~wYcVٟp3.e+;b2E¯s8~ZuB5|jzo/2>Yk۱WqHێ{*6=U]|Wum=wTh5q/\}yjMwo\99}{6\Q#e>]6uge 7Ϝ#ުWb&˫똬͕]5*{uSfQ핌ZpJK7GGW,)]Yb˧]. +7f^`FU들~<ܺ[2+_*nܲYe/OY*qfmxveZ?]J:즤H:f+օK<>o0Q)Wm`7Lf(;Xw^gu_ k_4~pMrꍛm&_8M4^Że,JJٖ,g̩;3刚i<;+>Xdvpn̖ͷ46U_nyLbxY+vKOj3WQd]~酇E [fH[Yz(gVײQ p5TZ,?wA^r1{w7:4uKNJI 3șyuzѩ;Fڹާey{1\+~?ې% iwڬҹ;S5 ų<.(tsG(l!xwm5[ү!ѻrdѓG#_v]m2Y>7KvyMU I/=xdwqȸL V3* I+~^6/!.>Sŋ)y[b.kShlǷO"9_{*6ыHr+ +ޖݸtq? ;_kl'=XxJD%[%lfp.xKm=Wz5tC(זՕ%Y'owv4˛_wfEpto?Mq!i:bnGqô yZ`M6hXmlTvOn{w}B=dEE{㣕Y1]:ADE%!:Sw_mc*ت֨/J)(׾?ZyI/_,ҼW=TvZl֬Og?*fѸa[[]o^7zMSls}'ޓyyIҵWcϬ/\KmPsٟzu|Io nWGFKyӟ͏\`g_=91h[j +Kw*Lx6Ѽ7pI2{7Mqui,w 3YNrݾvdT' l}eǗoX厳Smr}Sv;3ݵi={)+8IIjloT6vj_lz-Ӓۿ$jϿd[qkBb8;?g–^cʖry_ߺC[_$vK^7emGp~~K}IJ|v6]k5d;l7MaTyVvN⛠ڱsx67\gϺ/4~><1n]+:5FLiBZN[8t&ˍsBq̳W +,=휩_jd;kεh@& ɨG[ԛ_I?;xCZOUw> HP]UberOjh}ЧNx?I" Xv.̠X+5_ir5qNW孧e +~Vͷ)unRGEe:?Uړ-#lx5 ;c+<]:^DZuSo^bcwe^7̙I_UV/5ԍnXz׌nݏJ8zӟo7\>Tk]R?bɞ>jJ^JnDY/_5:=Wj/nhF5wݮSX!|Jj{V-[|ҋ%SWl\`.vGA'_,Y3< +/3:/-agSNx]DZ Wնtf/XY%7J:$3;j w\f1ʽQEvn7f?=Z`ϔWlOg"nؽaO +K$^e^OK&k2NC.guJ;gUKP[td֭{oV6t z2}qº=\!jyWwg9tO%.&vwYoutBn=VCnjMwb/++fwv4UD~z TX'IsWxQm$/\vdRJDG0xb wjݵu sLqtT +sK'ZjtEd_Sm2+Bݒ{:_O3gpm`mwL~__=gE-'\W)|{]ɳ.zY̽~Su}U\8QPnnv#xUury}eZSk7yڜ)埀]*oƏ_&>8}R'CƮ'* ֗&p^V8ܱ?+9\ +Լ71o=X1?kl [\~KLawG>c 4Ƕ nl?NEnKܓl'V*[I䥊sBbeKm2kUkMogU2#VM@T~u*Sߞ{a/E*ղ*M|u,UN~+s3:dſk{4c'*"=&Ÿ;,mQuʻ_erUBrO2+L,޻3%[mB\_.R ۊ ׮tƏo֟)bwv_oӼ\~/ߘlSnOuΓ{jB:`ğ;Ϲ0&_~̩WK Bdľ\s뷒z' ήDZG<\q6O}ίFs9X/\r^m>.IGz,0Ϻ;/cm>{(0 []Zr6awgSH$0\:=pvIRfo:I\yOԴZC^^鹌{ڊZ}*Ym\gf g♚*8_usmAna+ٔ=V[_cׇL\TQHKF͊k\Zn=[dds$o +.U%njS}ۥyXx⭫񊙌ZR}n=poMn& )p6N(;>R|ic$2\/s_sz[ny+ ^nT2 9Y1?5Uv}hmR6nv}HXU?~UΖ|=a \^N<~ɍlp7]Ҵ.Fʗ\iֻV4AhZ9WD Oj\>B /9;OGeセ]-*uZ2?hI,]' [^:"ڻнy7j%jUET1~ܲ=y.Ưwz{J.mԝ5n\axԥf%₄Ck,\mpU/][a9&&o;S[l˖-!on-guNo[#Pj̡ +}72OЗuyŏ2aXvO L6[b\l&%7NW2Ow[=˵(}͙kG:/zvxڮrA^?3kRmo46St71j{e̊xjklB}EZ*afgjP]\h1]^Ggoo[b踜[Cm?S&nu^繝j\|?ғ7V.vW7JԱ]@C\@reM}79[XIN}vc:q|[ߚCdw86Omuk궊,]1uC2c58c̜*o>~W_|5d.s|Qg+4,hfWجϯ>:G!=͞=7V9#ʛ5>))0~ZW Ɔ/f?Jc4[}}^D [nmx{DW +:i|Kgk&2z/LM{KVtUdoA/V hvfo= Gusd(t$o4-{ݿN&o}qq_wo?SpaetBAӭ3"r{Vh%y>oo>y*M9n;a}l\؇ +ϰjW_£㤍"'ΓU52˟)b~l'G>b^_2i9J~iea+Br"D=RWxj²m޽ Ko :esSCՅ}NY*}꽖q^ʢ͛:sj:*G9 y^llvωo]F4ml#]U:{mZcˬTU,1!6ۗ&O3o3sf\*7Qo~A¾SϨMO_ZK|WoN3jK^wϴ?D&8rM#bfgV{^qnN[{&gy-!$`QK +PNwv/,y%yM&Z4Yjxŭj㝷}ypDݕM ~dmufUTtb3Y۶W-cݼ= Ll-I_\]ko_v?_yuAۯ[(WC gXYͶ#qb>ʷD 0:w碀{M='0YGTٻ?guNL2l;hˮin7 ܯK"W?]X'+coQڧO N2o[aUr~ ߆1aز״>9d)3ncןװt&R\⤽ڢawN9IJ{ߞYg,\Q|Ŧ.eiwKX7IJzU)c(T}tȸ9L~4>oǬ&`2fYr)qo^)Sk?aT 8zٯ}.Q#dIR9EUt=Om<ݗWʺ'T&~a^79o 67_owabWZn괘&zqQp~AAS;o)HbLѝE\/ Hq MPynv)A]Z5vw r3W9e^ʔ?E[sZ~wh}<5vu*uU=O^7'KDuř/J-3(rnO3{xwVsk^cE %arVaRj> ;9ގaa3uvcCj+K'E5XPy_*3G 9ЙѲ;vJښM;t O905R=={*뇝FUk׶ν{0aKn*>~>ܶ{k>*//z J|'k9feu.e{2|Qx\} +k wxf_gpߢ_m]|acIy?j;]wSo:p1+V n9YZjXG@ܮnXo +Tgٳu[+h^7?׹EϹ4-_348S|XfX|ބ#tLL]'sr-M+.gb|eF_6}U0YRO _ԫK]n훴-GxfR;-zM}Q:MvY)+/ 'bo5Z[ٙ VG{U걵cTB5/Zw/&Ŭtßzm ܬ"˓)x5oy Ǯ%qv7Eѧ-V ߜm,y%2o/~Ÿnlj5YR6ܳ闤={*̔ǏX8>Y}Sؒygzջ?n;J&w,vyUȑIilEZ~#NΆebĘu^,"1=nSzpԙ]W\,3\:R3g#Iuz&J^b]{ԟh xUԧWd}Z GEzϝj>I{$|s89ZEGx邎7}wmڐcoN&];7cQosy#m67c+U玩;? +N%?"6(sWuC#?O8p؉/Ϟ|QQ\Y=ΰ0K9pš5bִNf|n{ReƴMS_+L;^z7C<0,Lz"#nRwxT®71nMv&4ssdW窝,Jڷ@]]=Tm̺3Wfsc+ Z~+LZX;#ߕ̹V+M75KWcdYk'}FHVJHh,E;=/ ۲xbJB0gnQ^% a3RAu'ݸe:|<yu7KUY`vewrMN=ع._xMb5/Ѡj'GR_k{9c= kLK?}8_cSؾ=BcVN`{-KTk-7v#mc VL\6$͛~10{#`sh߂GNnZ{CS49@EQ'Q~~~\ޙ}N"~JƆ y6nSaμs%s=6*W^p+j+PC:J^z=a9)83v(jN &VW7\w)f $o.}YVJwWFhyy5_{]}{E|=RkwZ'\+t7SW8]t;5o^mm>qgfLSVz`l}8K'ˮ*uj5[msMծՋz#-150#',u^w Μ7u&?{4''xHe=gp+QdmpЃMZUJdP8uٷ]Zn/hPrW_ ް8gm?ŞKwUN%so_s/ 6U״|͒=tҝrŭ ;_2[c /&ϽyxjnOB>?pć~xUݬQUy Y-Wh˔[qsƹZr_sSf+'[<)姁gj^V[uw?x!y.MWUOڡ7T~{#➆5-gd=:y6kvoO͟egHFE]y:쁫9|9T1V[_|b:3RՅ}zNX!-tK;³ˋmXGD鵿j╌?}>sw9_ΖxƜSWx0kX±PUm/eqWҟ+&l=xtcugg **YS19ČǸ =~EF9[׮0F{K +6DSe[7WTyލ5.x:CO/ln-&rP?Q~zK8vyw]I!su[d)%-?۸?ćW>sxsd#oavѴ ) *LX2\ gfXs:;ˬGY~[s +7}YO#7<k#ҿVq>u}ˍQ$\|aY??{i5%>+61bxq0YqtW c=bucmbVfuai0095Eprf? +ڥ/7\?Dl8P3\!fS1S׿ + c+p{2{mlfj[dc6a⎟ +?2wM{[VGeҧ=tVM=-ΣnY΁wJ{gSYm>.yro{D I;~3}U]Iל[8)s('_A,6|.S?=6貒@S2C:x7Ό׾by{fZ/u:&/Z17oenW'wDa?ߘoJz7.dYMVFRSMlV|43Y!#u,/7*NxoCm*k8;fOx\f%vN15b86zQ$1Yũj,S;yueIOJsK֖hKyp +Y]Ѽt&[yk珓%~^ʸ˅³4>'s%fYr.UV3Z/wZRXoߤVU׭zl/XW/5ֽ{V8U_ƛ9pͻWZi]{޿Ui9,we[32WĤ9R8r.EGn=  +]L5Kէ47nKU_2_}kh9+6skٝ-}'l kj.( Zbe+X&JR}M;ꊧj_7!aKDK\ =ybNoĭI ە՚ +{3b9YCi47v{Oyxxven,Q==; hK}Ǖ1~w9_=UrbQ ;_w>\Cn5~ϐ4rMS:ҵݥGW7mTݜy6NCUi{{ܲ +3Qf7ksٿlmmb_>|ŭ|y9?PM{&3_: +{z{ksܔg:?2Z}gOF{?j,*/~sLJ҃kla-_w[VicJ7(~骜LoQvKoYk:'e1iTI[i+N]Qbꃩ{uqE#[oXaDl{-esyP^n΀y篾8}p˭;xOC#99k)X߹V9:{n\~kMГK.?Ȳ W|dլ)3'.u(}}Dأ73!mܯ_y';Ǭ@ֺra,zZ~3XRtO<K)ٻͯ4c-P&s*ZxX3S$'ީ-lwzȆM³2^~nS_]Y_@*jǎ6l6PlwsEH麇:_T8.!TTgOnu-t`OeT2{.9KlU qz=&;6?^ܣ{ςז'}&n.ϾZ'eq${.hl\D͍G/ :;r{T=M̵!M̖'N&Z<=eq86}ǙۧO[.Ƚ0oE<٥[,HN@&CSz'W}ɓqv_ܽ>gz/}V8sUDJFu2ڧ-xgw&Cu̿^鹇 6ܛnjݜ‘u=;>|ߨ%2N_v28?+jVܷ#t~Y3Ql 6\bE+'fr{ߕGnvle^Ϻs_fJ^n>zY˄-~26\,yFy߆^psI?zG-v'-RpW>lp2^͙5Z UT/X(6JTgQ% 뵭}lxMNҊJ'ps]n'5՝h1/i;!Y>aw}{y;kfWmh\w̸mC[&i=dp›4[nm[w!B}%=_H֒ip{ 62N۽2#_]TX: ы<_>8Qԣz  r>M ~aZ/k Yex.5Mu} +޶3SJ'(t:l)kZ?=ZjWG6m4gyízrš>DS8"5'bmB t v4>vxق>蟕lQLgVVDݕw_9A*W7Z޶cf/gmz .4/, +ov~ԟ/=w#}[^1:/ʳ'*a gk^ٛnǧI-ߢw}B,3nhdwT1WuA-l^9mJ}X/yfگsJEr~yIg>{c苶=ž2`UNվ =g{?/^Ъ-|ڟ:Go{&+]ocs&v{?YyHW +<">6q[<3VcIi>\qGFU=su,^NzKĽ/[O73ZʕUWbDn^]Xm{.InpeB=5s$ݽs"WkϪ`ע?DQ137:@;CYnrӵ>qǴwX}SU!'vƝm jZzɾ[3kEkDzV̟`v/+C Ƅ9u/]U.-^,W!pַ̓Z_MvIB뷬=qQ.o1oV"+Nw=-΅"oFMu9FߨmVr*C.Jl`"rmˎ/{@72?e\=7t FC+ڥ?D$Z|R{MR^PTb7޹-4(+;㓛WUMU͌[dZx+SV_jgPÁ lt1oHX]DVSV~욜^Z%~J3b4c^ޮ'h+(FƺH+7.+\߰2s曥|Pm'mBpJ&\qEwr~'*sCfsKYzޞzǖ\>?iӃGB?x|so-jg ;=*|53W2-^PDŽHM_;7->ȳk&߇M^oA@FA67vU{^@^]ov3}?hvx/fUglraRfGRU.};wZ|I /pSg=ig/Zjs Umf2Pl3^ձ%<V8gDrì]Zbֳco={5Nr_esͫC4]9$cxk=V\.3y$Y,-^r SWn'p2{ۄgǺ\U̽A%;&hq/X&I@Iwsݛ%/}<&Wݧ]ղR)` 嬧B,16.B^Vh#'e uo8bM9>ͦU9|Җk9t}vg__v3D|Mߘ;- yL-]5ҳNjmˉiV$`jV\W@V]混{c,!*/-C٫o2,i[tǗsZ? iI?R|,~aZ38x' +yZ +]uvi.UV3d~a읗n>c;qq·%ȰsankϷuK ri3K_6({ZROCzv޳KaNgV_rWbuyWU묹`ua4|=8IG*醳XlY5y ܦw/ [WKH._VFKWa^ϝOKobInՆfٮw`k̐o$GgL^%rQNqbI5-ru~2Bʗx=Ǐۍ;+W>)2[1$gׂi +T>fn}|ڳ 3/|mp: oǽ}mߪ[tm^dYn7.Teo}j5MD"4XUW~?qrɤ3* +o'hų.+\c7?F]6vF2u:OGW}JBKm_&!xKo;+q/mرYꩲ6K +~N|)0kmg[EOCYSvʼ3윛fjzY(y)emv]3.3;mUd"s.Kﭝd9}uݛPtCĽY_z$5;e O#{jMĢxcemTdLp'7N +:fj&NX~ބ4\k>?-ЉuIaa:E>02ͤ/! 7os'[wNR-<Ls_CuRGgnw&_a-1fl W}5uUse2NYnL{ nzNQqrdv{f;_>{MQ9.ퟴkܟa_';ufD>6vWŬ 'u5 +zermNxra6=s77b<@)սNyz˴SG<9utcuęKfiw3JG0X^ $ Ʈsٞ.ސJHg'ϗ~P1YĹZP^xɉ, 6}ba~$jWwf=^c1dž9 +6gޕx͍Oq)gq|S^.a2el:rX9sE+Ҋg̱Y\WxBX4],-[ +?~غ+NnQ$]ٹ/ S'~Ki~]2 +.3s)mc`[>& {\\& ]ԇo)vayq-G_qLn֎q~L?<`P#BW'اK[&}]zyQ] vupL ٧z^SJy5mg$Fu񎹜)Ü#coD>}y.;Nn.~ί ʰ&'{T?-74ڵ'6Qv5ft Qbm^2!_SmyJZ O6*l5ߏN;3- ,,mmLP cKĤczґss{^t96SòMQSٙS>i^¸id]kk>fRĝϷj* +4>sśqo װT+fLZb ZV!uZ>oGl;ZIJy8-$n~o9׵tzӝ\Q1Qct;wJq w<6u +]sgr=c=V;v-tR2[\},b!/$W޽Y~bH_Qk퍸Na˳_G6uxǾp'~5(k2=~$mF›t]Vx9gKMO 7sye@Қ Yv{`<8mg;zi驩=cW~xzV˲HmIs4<Ǚ >|ziNz'u4@%Eg׷;rI)O30ObٔM  }9s:R gV9TΖXN2ܣ3f0o3gnQWהzU;o^] v}acΚ֐2׭嵢X֬bO)3j >~_ho miUNW;5:RXZPF+sx~r5fk**m-#Q} ǻY|]Q;KT*)lep0 b7oY:Nuu.?9˱ģ,x o=eI'qS<~#)ԩ[onqsMȶϵ:Xu1}iBv,t8a5s:Y(6k<81'!K;2FqLkY~{|[n[)'hu.bjiQpWEK^&eօ]["^0!ruh҉V&'ϸq 4:BPޥʅ?*t| x{ +n]<`az1vbP7v& v]Q}QZCu=T;x=wWJ,rŧ%AS$mgmoduwQN1w.?m"˙VDJ F-QV܊;Vk([ۓ oyxޮ`w=W {˧Xa)|GR6{t.Zn䭲]l{ f+=L;vQCcB%+Sۘ/M(ryʇw{|}gqs)&WBdˁG5Ol]x3WR}Vp#+ꫫ? 9_a?՛.*+Ӗ)vܻw!.w֯ⵦ~W$=ׁi%?Nپs]#v_)-H\I_{$wvkӧ+˵7l)SCB/8-}g֓]SV%o)?\4EL;2QbΏij#[1?ٮ0]=鼗 +L}hr'Wuɶ5sJ̖^wB}muړW{vL ص͟Amǔ ,rw=G + &8.#eu+Cϟ>-U8<5cK` wc͐CZ9W~f[kZƫ(Gly\u-u3Ζ(wwGIw]4M8-T&u[LǘӼ^oclf⋵?H,iӇr 7 r6Kq=_n8>jP㙎6{f@rQO}f.:hK藲_E^u{4]96qsoǣcM>¸[0{dK]tv>m'8U!Г+_5w~¡\d%|}G%w=ݝ$'ZzqJ\ݱN~ZV<=':38kd +Oke3{ogRbkƕ˷hdPri__;;m-nƼ=5SO!qmJ: y8K}!`sONg/'̻t,B۫k? VO8CAG4-o.6K;aIgyl  ph.HW[A_K-}>6YUާG +6X;b +EOe'{X|~o]JRo~KY*Ϸk4Wf.[CNEbGXOi6 +WWl"_,_usu=,O홦yI{)ln˷*xlƹ]a'/xƞ-{\ϻC\;fTMPSO\apo22h5Nv?׼w3O4tŔuMkVEz1ߥLg9ˮ_tCmQ9.yYLY8N⬇2l2oU_ur/cƬ,4ou3_=QIxf.8K=W.}r6'5cf^lZ=W6Yo~J&#Qs)ɖ-2ckcm*bSS1|׺岩R)\0 {ٲ.{OOMh 6]O2JV*+-8bxS^m~iqk"zf=g@ltT93[|tzϾЍZdR/Ӣf_|[iřX[5=woNjRDKq̹`;繮 +ݴKw{%\`+:g_-kӂeyǻ%je]/'fmq{ÜQݖj mεGXvw݁yH=[v;';t? -9(]٫ EGwy3/v"ߋz/~0\"N}n۾0^}Hъ.|?VR8:Ϭܶ[w9yEЦɓ֭w߭d܁nfUNOSJ[ZyI/Le4+ٸgl?;+O׮tlpMzqT_;z, d_-ioĐl|+4z=s걋L݁kt[^خZyl*)^.i&d2hҰ O>wFˏM^Um+dlbgg@1w8^tpdϻj{5\)\'_jGƚ߿|s~ C~qʿճRˬ%sxr‰ݫUg}]=aV^0v +_|qn­4@Y,NMQ1SgՖ]J6yީxo蜙>Y"FY M=,JEijª^}Q>gصnO8s?EuS~BZqmߛtʕ+\|W[Ë9#,tfV 9dZ疻B&'~}ܷf**}V2ƾ/pgkH~tݫ~W\ZΈj[wowss/vXq>ϔ =6fϷeϹ"76<_|{&ٴ|vÙQl?m8v1="_wNt=vrc5\JkBӖ]Ή}x;6mn}~ͻ' 6')R|ڜJ7WO0|^:SOͱ=}3ġ"_׽9eMGE +\s2ǽYGVII_tK|FeCCrK7L*o3G[.En]yҰj^쿪}?8J2IߜhS ޾DKl~Xq|/gJR 4I<,m )=R|ͼ9o}ShyҤIv-1|g@y7]r+Q }+燶}8P8سՎ\7W/^TH!%guV*=xb;VqK~s`yE}m>̩Ws|#Y2 +m*ľMrbXzaGF]MjnfgƬ_f9+7Έl=\Ԓ5fʝϕ7K5yΌ#TbE9þ~6G_^{|!Wʵe=jj{&-}qZU⎽1Ary#dAǫL)'ϏI}Y r%ՓsCg\2_m4?'ϕ6: -@QY¡gf;W,0i닒Q?g4/A?>| s[)j۹^Oz%!9ҧWy5{'ITm9.e*xvZK(ybLŪVӗI`**$W+2 8HЅM')=Xc5Tv:̷iV4 X'e.z6k?~%3oV3܍xn:pOmßȬXQbi5 +ﻩx,Q,r92>Du};seEa.%&sEwZa3:)#}fZ}s6,5*bkf,f(Gz᠘3}?wBv润d +w9{'W}{UhL?Y(, +u^W75-fer?-x潞W6M:whZկ3w~q)Ya`2:Uqt+:.:WQ*i:\:L,>s?)'}N߿)Ӗ]L}-]ͼJ{ϼ~];,1[Jv/MضCVcko +Reẅ[xP`͂ܺ')Hi9mᆷ%uI"Ϻ~=jӭgRNK'_2-{Άmi'g>s˾WgpaӃom-/[玳 οG7ׯR1:C+Ȣ҉wZQМIlBgMVlLqJaOڪs`Y{Cյh=E;X[ _(/Z<ꇿ2BMk ۵SEXM /e丳sk9yP0^ě[\l!ٙˤBVܜſ}Q;nwgC՛ Ng/͟ʭqVM{jE\*H̵W75%m]!f,OE(KLz}Öe**WO@ݚ]RrEVZ{]{gr>Jҟ:Y;WE0/® R֢/t' 9#ٵ"`Ӭ<gѪ.p٦&]NW{wq>kI~ egiZ(gLzjH>Ku +/zz'ei-4붍ʝN0cɇo7 K\2b*'zwl( lz6߿^\t0G/݆wܓ5-kgM۠j/+;|2ߧ 9339p + ;Wu%^Gf}, Kދn| .89Wtķt?plՓRbMrr>ݘUώqG*|v*f6[K=,/_%r9tPis'Xx^p!9ka봩n.a~RG[_ksGBwVg)k|8~].Յsm,\r{5$048ï$esvKy=k &1-Pp ]8iΔs:N[X菌M.!9O[f,kwjwNaA" >7:{߾8=f!+gto{ODB_Hn kA&2Ό9᫇Žt]_ +yj뼈`/UNtna3:=ɰ;vK\w[Г*~|q]ΣQ\\#a~N /ũ_ynmue \= +b 9cPM{c?ojV[a-9QeoPp.q?=j*Smsy}&^\[ZyW"1n$am+dp Ǯ ۳Jo,dُêT61ܚTslWK^^V +5>mB[0 }"gj"cKl\?JouzS؅nl}c3e^WVK9lv͛xXN|bGdv/(X[;?ܯ1Y=G}RdΈ-.V`޾2Ż+(lYhGq7yǰlrCњr]GJ{(obi2A/=D=O5P0Kɹ*O<+bgm]?_%m#|.ԨLvaoQ ;4/oZ]Ў/&?aR yhs}bnEx}a?ˡ%fڥkd5Z?;e •kTWWv(s, Mj48´lIgo9pB|3vm}0)̿&6i9ֆ74)QUNn›IMr7 rW=l{Ba?Hp,ړXn RNȊvrhgS?RW0]HN-:^˗cbI_ ۳US_?~ojqbJS=i+:iS1zm_frOh[7o.ңBη{w:zrMǷ.|thJEҢ^t_Vmi~QzbV^v4uJv\TNe6e/yMх3 Mpm]8,&kxr8нͯyg ꠇ$ク/U-r@ͷqEӾhit(\dW_thַifIgmݭS: +^72ڻIwQi #L'soճעkWdǠ5{R.]pɋۖ}c]̌FOͫ?sUtT}5lov1];Vu&|BXNӂeEVZrV7yswӁkw55 ^ލKwzW?mh[Jվ77Vla[LKYdQE:g|B3QK>z>gn!V3.?+}QvڭU3M^Tv_LO/䨜ӒRJk3~T5{ÐpN|kNcgZnj>wo~bY|O7褀%W Rv;j熫drOH>w꿚ikhH|hJ_-r/Y{l;:)Wnř/R7 +dЧ%~~K9u&7ע8}EdX}#'sYO '>nw]U|Āƻ!3.J?Sĉi߻*,SU"D= vjgzrݚkjW[|'bY~͗WFom>Ȏ5ww6s.i8ݜk x'6+e{^ۙ^|s} o1zy/kWy։\t-gωJ̆ Ɍ[7/,Vs? _㛷ܲQs<\{6KV7'v*VzXY]*5aߡWϊpM0 ˹v\u\fTl{7Se7rh׊3>>c 0OtpRbEn*Yqa9B~LSQ~yvqA||%[uWֵ[ypB۾۲\V3޺{h֢7Nw`T ~9V.ikyxԙ-b ^{ګ 5>7l)+ˏ33ߐ7U0]srDOR2lRՒv;7]Wח5&rPMSd#zحڱiGc>q˾g{ˮy_d5tz{eJ"17,5IWB[޹8|' lr{筊Su=^?,uܟuɕcKOoXaۋ^]Ynfz$AmGށ:n̵V^;[q {̢?}JhPQѥ|'l:}]{XrcxIަ ?[3izLI9ӱ\QWRBV-6+3Һۇ?:woe=yTNrvI rfV`.yLj9z-WqXqwxd|I괌fpq]2ȣuq?ze/fXW=JNsijrdOǙ{[ul I~= |7}n=%?叩2ߛNP?5~֩eSm-_>*VSiN;䫻IsöuO_?ͫͻx"~MU]w?2E9EK*NpL^Yo%Jro^:?ܪjz_5Ӝy$.e/ gcҲPG°W7܋Wxy{~eWXS߼{L~  +}޸m i|7`_8a?Awv qe +Pg` :g8>-BuƔK̭ +N]GhqfcK,͝JS=0mjo[i$1qŜ\&4VhAx˽_lV:9.gxXfV Q'L{nYd Y&ȷ z7։(ψ~4oE[\Sb_)3^y["δrɓ#ؘQPs{~LIlX^Ce3]o.cٴ=wN ۡċ[{H_Ow:/^˹^7#h'i'/%X2uȏ塆mӿ]xfB{ma?Y ?ⵥVxiQ4z?woShַzÊ}Gf~cf3v#6_ǩYGDXʚ:*=^عtɵGL 8aтsf>rnSaa*wmv+,W'OuKnv٢w'Z,$>c_fg|k-~HkܒmIE +w[68Y.8.~ͥE'J3om}vOZ$3iJqF4תȈb9,w&pW\}u<vkY+}ߒRxb6mᶕ7 +*:v6?7-Z?xzbצK&R&J^sOV+=m~(1vAxƓzYן≷=X<ÑkΗѹS +?}x4/q++ù[Xg2htCCC2%i1j_~CKɣ2f_Ϛ[t%/6lM_.PtNB^,YIkoum;O:zpl,78?sǝ湹S[Yl{];LIOL`{OBO_<6{ٿ n#9utĊm,XeFjsD,o6I~v;z64޴3zj슿-1vLbԺT=frB:lxm~/KiK邇3yc,ug_Lv1-޻^{vWќ} +[:0Ɏ~{3JRw Y0_Թל/m?t>5<}2=UxI~Gn͖gVs= 6?{d)'8cxբǽt;k_]pΈQ\^U2 +8u +J*}i(e{qngֿGԻ!a+o/78IOeJjBŷu>͘lƖa%֑2D~(_prщ[:%.f{sŽ_xVV\f!ŇU +x߸؜w{xء n ڲ6?!spǮfV3ƿ0Wn5. !O|Z;Jn{᭟/k=ٝ^(N"Ǝ.ȓUg4ZVhym7:pN_ i&+ɢTo볨]atV;{lfM"4YN׊9/q;`BR,V.W@'- '2*O=TqН{dj9'p5zҞڦ9)T-;C0mwn'~pG;%L'+1Zʷ8YLbo=5TWכ97\t]gf˼/欏n.m(ՎL\"#>dx#{1U'*rXxiNKtU7v`]SԶ9uGO˺#e8:EZB.,:,+1:hl{ergKGkܚ}^n?hsd\lqO>fx9ѰFn3++L\p\#mu)돓="XNt:ybDzߤ: ˻_S `~ݼiNN}kC^N>ϪuwwOH\m?i3nQ7]2jsx!߼8l/@΂&FbkOV_9oZ8cŚ=E3_d7fWY/gXf[]27uݍ|(ɮxCg\N~ays+%~]{{o]$ s5nxbw܊F5e1IJO$+,:hәݗ/xT0eCK-96}FXyi^^ͷ}" w͞{9 +o=򝻣fuNj/X_اⰒTiY{n٬gTnϞ6U|͏.X힧SoVNQ8mO-ou)}X$EB̏Os1~g˘WլdP_]߰7,ϗN}g蝒?>*?~"W'UfG/\efkZOxʥ|)}MsLVޖ?f5Y .v +(LޓsO'.ժԌ+[}JwvJY]}9[QV8u~{̊1e.ܰ]yDyrkgbr7t{b%,gZ";Ĉ]_ ul1N7 _wdEyҌ@⮙}e +[[郝 +'C>MJAaj]˷sGg}fV|UeoU[z eپ7ܞ~}lW&FK_wG-}ebW~O~x_D]\ںϏo_H>-&6:`ܖ~ISv%pY`IRQ ט-]sԝˉX5r˽;4&M?-H-˦tݢoW؇.<g ҄IOZggr]f^zI; *7LrR/`Y7jzEF.W'$.^)e_i׽Yޱs6Oxw +FֽOo\Z5y6}>k +-?L9]vݩ Ư_yA/}ӏH]{(%O bwG{&zjSs/+F^[wWI.4gS/G)(Tn4]['ycSIuotEL3hFgcsJ}/}Y&GM,?3v] S.+.w]O+¶+xҹ?_TL#ޠmdR9Im*N'/ɳ7z}b)8K)o\@nﭛ {23]1GuW]7t7żb]`9wwxz+Kkm?>_'jѢ>:O6rnr'7޺±ٶE\U@oԇnx񑈺Mz^/'U Gl1/&ů!7)Ջ{wWnIjfgNY[*}{cWNo B$mf +`raE%.4!(w=R]x]QEYq>m _Wڋb߬dܥ;m_u{ۢ噾3/,zRCV?5M^箦MKt@3on_kZ(1aKkYT^X)jMbgGL}~]>Lڅ-z43ȟ,Xmjs1!m*J'k^9xuks_l8({xO+Olӌ8xsAOK񎣒:R .)FN3Q}]ڂ_7|m`=_wE|&/rѴMԮoku~~_UEY.i%ǔ> 9g4d+ƺ-zfnYh9q!kKזu= 6Zpv_٫vLzR;ێ#V+.%l):ђsjL~>\[o ?lxdg+w+c+~a[ yϹ,'C÷iy {Mx'sV<WbC~de;{G|YѯkfZ>}l z,Ebʣ[gg\!i;j'HⲇV\ꟴgLM:6I1,/Yl 5p\}uR}C˛x <-Kʝ{Dń,ݹ7M9F`폶+#BTMaykd_w&4L C\ NR]pwM^ l?ʧ?zqwI߫ q[FSi)ˑ X漚y]zolvN/>2gO^؂v:\f׋WL^~Wq}ޮO0{AǍ^9g]_~vhZ7l6+4s%ke^}}}BK. WJ^`bu[t| &Sn}}`eV'}I-}qh֌[ ?ו䱭'UlPsOXb,q?vO͗ ~dm|9 8l,,<~O'z×ֱLzwGƬ!eM*labsnu#)|<9Q͕_[վgO\%zIb{-}f/m +MNٲiƌ|@hݳgfq&+\3aӞ0#N<`nqMM~e4]1Wdm9*]Rq݇9"7N=+~M#c>(;?/iJC}n$svRӹO&-%'lя^2Sg]Sd/'5KY۷R/+6t\_ +,6[s&e9gưSkmn%v-jqNϽYcNjV/ݛsʇ]Wݾ]׍ng:/.:WU ^~{#_o8_\r{ j>gc灜u 5Ken:7'`yP3=2yeuh--)%񏯆_Gĩv.5:|¢jL}7?d볓= +E +o~)׶ ]UlWuqOux׼_xE>vWU5(YElKf.pK][Yղ9Fk{Ox+O0l +#aՒ_&O¾oܳuY|ҽruLYG^Lc :z}vnYaͬvgeݙ;൛~ oUm=\sÛ~mxW;~YD}$:p"] mwWfV7ZV[u㯫5kiǦr3Yۇe ~Nmʟ!vH,3mpL- OpÙ%jEJg8$ Y8dn'TMLuz6-%skKS߷y\~AQ~So;|4N ϼs8W=9ݯ{umk{ +FN.~#BoL~Ehٷlߜ\ϔdΉJSnm6_;UJ{UMHx<0L[S笚ş] + \RR^`ȥ1eŏm;SJSq? ~^ +ùKB;3o쒭[B簭Ρ_EG]zXEdavmM [|޶+֎3<0m_DKZ7]g/=Xz6M/e'&\2^[? Yſ)4~^mgRyG8Z<82]TsnR_ڲuҭ>&&ڜiqE ~O,U;:[{OnsjreMw =Ovpܶ'?FuFze1>>[Tt՝A';?HK/jOVۿ<n~\4!OoffKw;;"~zNKCDYfc!k+D3{{c +׎}ws{*g7@̺˞ܳP?88bSIuJL 3n|ZiK#.љB3,tT3&2< W9y3ir\4oD6Y2eΗ{C4W9|n0?Y"hgr4/UwYF9lY"ϣy,/^UMe9|VT|{Sg_:}hml~/NMq$3k|ViaWJx'V[xF" ֳ3od7,pnIM3mlSd­¦>f=tp$f*67oQoy[}pluRq=':>ꡅ_y}l¤R +=t|wEPKƢe]TP=Y4U[!񗾚ʽq{Ƥ>:xrmGo(b?bl=Uf KVnR5 ٰgO:'IgY=ۚJk>Uz,0زeRk_v{?\HsaEeهXLf1;ٍow7݄:73-J +Os0/kdC3Lry]]{ Բkӿ}Em&eVyf[yU#:ussc~~!۰(/b_]MЎ)'@Eӻf))md5!)CQ6<;)d{{ޖ%;lSr3mr/Ͻ'2UӒ&' z:S쥃^쫽%}?nMDLfͳ]RIXP-v^Z?5Sy4CFy7Szs=k ;tIb;gI`KȠ3B[ݲwM=D]ϾxpE,wGR>uDR4ؤ^(q餮6</=& %Ae)W%KWq[#({Zgm; "d|>!cP{,įt7:Y3OxE@s{?WPe$U߲3n8=oڌ +iܛ9~k;y]fJEj݌_84CTn 7\v%] ozu%国g<]9߶8>A;NཛF:g:8XnHyKǛzrR#%9EL߷!|'ޚbl<_a5B@yWXg1\Wi X1AkS3Zu)/=1f=Ξ9r/iY5[pj_w?Ȼ;mz)CwkvlXFOcyFm~X̗ =E.gv-bnX5=Izrٽ6%|h5w +s3w*UȾXS5ʇ&OSU뚟_d)]ڕ +Z^i}8,'O+OtH5M~RO:ϛ8UPꅦiOqcK)_Z2ASօ +b'ٻOՊ lK9v' PcᢳK|NMڅYs9:4DG[~:vaVm:帉?'ݱm`ǺճuyTnb2t-]⻞޵y=:mG԰gts^~.8lL 3&}縵u9JO[lu,ZSNiaӺs4crqzKΟgTmSp sijwf?E݇sg^5Ii?y@LC?Cõ_*N^kٺ5>tht=AkRJf1YD*+ڌ tp.*j̾|I|bOSW\uE.^<2 yn${:4C.Nӗ}dǼŝO4|W)<U&oݘ\2X|hWOOc+8-336x=[KIY"y>NY_piSΆ5Gҫy*iL|+eK<=CΜEe ׻8~z~h\x^Wy}x5Jy.{GI u)I­el۬WvRJԎ 9jc9֥ܚz +5o?foyó ˴OLzTDoܔ~; lO9ꖰXPX})q˔g}h: 'gtΎ:h~ڢ|/oMY?CY@sٴm.|m>i kvHJA3jڴK(p.']V bԫ v,{5ƹiַRg_ta]%,ޓVLyvf sV}ώǹQ&iͿbQvn|UI{i<5oߒS0}seӽcb9]:yf#bRے^i=ʱ =WdNCCy)fwX$1kџKgrnwiUNP:=וϘ)_OnRTӁwZUiV=ORuS}ҍ ݯռL:<{rhͦ}KݲK=u|χC'ŒV)3MZ\w>M*բ#s68C+r~䗯1*>{%̵t)t^QN|,%ɋ|r5FZ -]\>kk+)g箧7o08yRɊ3V]lOl~DO/O&:M_u+D7Z_\sP~Lkc5il'6MUy}7hâ;~3lP/.9}ǹ+v o*O}zm?beWآeumY3W.R(#cZcWx Yx>墒XVMM÷z9u3 +Ox,Cڧ{?)an|e˓c[b'%dݶKU]󬷱[L{,>a˂zo|84WW(Un)X-,N%Z%A6H2 }lf*s)~/?-.GOy.y˙+}~Al@bu #T}vh^}SL}Y`,Y˞b5sÌwٶ<*^'@a[ÒuN=ך}s &D3plpZקĿX0i*Hg`8rS/$F+_:|rߙ{^C k RONaM[= 3;ʶuZ +dXdҔ]syKo~ݺɦ3D(sX~]̤/fBbKnˢҮoOfb$cVѝEΉ={i5;\Kt[7nINZYm9 {o1BkV2}]wf<%i;T^k 3qlCkUwAl˾3wRxX~5>UkzRX+~#-NzW= Ug/"KT'}o~m;,gߤÓBn\+Q|’E'SvLP>Hv?eݣyCMT^,W\{ +3g~HXk,;[y {^\.9$ث_]'WU?/>z;AS-{Uog2~?m\VGgѹ + +a 9k{៾X`yͳUUwy$wɿs>_Kix$+/)n^vr˵KX"solךu?Dl'=/О8imȔ8?ݎ/#Y$'J`9(WfHg{*0jxےse +~Ltgvn[j)[`;ٷo~y/"/~ EHE;&^Ϭﻂp&)ϪKN8y٢Վp-W3A^iE''͊#jozZglmRϝO-czZ;ߟr#MD}%lwn8o;]Uѓܺڙ?v&rqv*}lxm ӹwYJջe Eu}JIuàw a\|ya5wfkmLhe{&+i~0oD6M)OKK:+۾v*￲fzNy,Wbԋ⸂#^>Vt©79G^zdsʣ%g8޲ƨg],ˑyHտ3}?G"ITŒjھdk֝dܗy=qMK੍:ӬIeV{D vEI,9[ٽ0W%q/]gk7ckuq]&q_Bm0J:UzcaWrob{'c@7>OGdg/ʫ)vn ܝ/Ã-$qjY*[xvog-MGl0Shn^!opNj~I1n}mh9mikN6jpqq?sZ4w쏹 t}jߋTHOtVv S{m=8[Oօc_[OrOȡKfP,F`Ts?p5zt?=i^/Di5@|یmk ddժ_3֒^թ}θzyN=5oMCiޮI~٦Yi}KmMa̍"^JmttR~Rܱ^g9pW<(gZ57.- ݞ,OܲK.2? 9K4}Zx+ؽAy ?S-w9.Qy~ ,?mƶ\U 2VIe7wL8mT~C@Q?ױMYg+Z'wɻJ}d{t'oo6ض2Ǜ7r,EۤW;\Ԝ'0[euGTGX#yElӗ;'ŦGIa/'rϊ+TH^}xWarYu~ͪ-~;(}IOAGʖ3'gVʸgru!S^Le-pSUXB[]fr2 VzVbdڙyCR;uC/SӛmɻdV _MSn7:޷'iNgyKVjۚޤ~k晴~9xH)~l8YY(nJ.g>9|̤(7N[uHI]+WmNXywEtn{弚Χneǭ~oGEmtCWm+8#ѫFylll]鉍gZBrw7SXz#(KH\2%uO/9+:_|9O*}&Svn+`)sgϼ{{wd9SlRv&N+\[;W]ǥ^gm;"N_Ëkl|>6"sLGuUbgB=O;#\rPG"R؟Z[dcF>V[I48MLkuX'V+/g:Q]tYl:otd_8O5 +/mq;s͍-CEʷKF(w]пl&ew'I>1c97 +!{m + +2y?s+p-T[Bޕe~EZ^+]`|_/,e^`4 )"s6߰gwlUk6p19}N"Z"5,׺UNm:O;{ĔkqY٣; +#dJKusmD4SӦ%['3&Is9{+}(K߷ 7rZ˱,Ije sz)#G/dhR )vN?vX2uLrR;ifԙ˱?LUfS7W~qp`ڢ3WSR<2,)db+\]]ܷUo*֚ĝS\"/wL<~h̩3$MH +93O"cj>?+׺)1NWeُ|%Gu2J"6XF[#pֳnN. h[_*4),Y#f?w[*}41~=`CNлSXy_[ğ.E{glN~d&辔!uem3_el4dnc}1> S5V01O~4E۷ Wx*UqݛWlլHl"%|uׂg!Yڇv| bbjm'uHZqsG<\~߾/jŷ\;OHsqنK3n]kUiJ˖:gVj"ӓ5pS2a5i^Iǃbߵ;}#E؃ +5r,ػѦoBA,WoY\#;YcɜřG9o(5d' 1Rsq=Z+#xNJx7bѭR:Mcoz3+ի$))oO[~ WUD>Y+vYsOi'&&tJ)֛t$V~.U<6i#M "Wa~ߥ9]p;Q>]p.#1@Ɗ;>սx:U18g2})[=+kB@З L$ٿ2m?f8bA:'4^>ĥl{Z9< J7~{~=)GvrjQ"@Њ3d*}cW^_~]qi +>lH8Ó­/?"]3 +v_sWPJ. 6~ES_6E]9c|*wO-cWW[`Te͢~L(8+iNhgsO}yyW.f1_{ȳgrm'L`9嗓;9Ӿ +Lx+Wg0߽m޼Wg~Ӆg_NT\vb7jro+7MX?;={j䯒U}ONb+r'4k{)s PxYr`;?RNooh+Ll_td<;36%e4ϒ{qG'o\o gLP_'R$ι 3;є-}-7ٵ@z *uoWQy"\_ЖYJޟjۨc߇ߜOwCE;,ZzVyElK*O)fm ̍|qk6;׬m_~!gA5,r-H[ǹX9841l&358V$SRX ܳC[sYťUיC 'kz- ϶Й9>o*w}]q]S%Nm;8-YXϥR_+8ZLx5j7\t.rȏW6׿{Eީީ;Y9ye\NcO-~xjbk;zmxiS=7xƕN2XƮM۟c~skx +;0aRE!n :NwN;BfWqQD՜Zd|%AR0w?E'lTUfő]7ϛ|y ?IvuҔjbn/pTtHZr&rݍS-;Tmw-gUAQ/rֽN]߫3H6Ѻj^=O?[Yޙ6'y }=g~2+^J9Mey}Wo^57y:DnQg񡞏т}߻NW*pHˇϨj^g]ل .k|!i>s|Hm[n7iז1iM{º˛WpL93pq.^?kȢol\wd@BjT171Pu믭 +vIg^ {nZį6{}7g>_XFf ͧAg")oX]2NUc[̓/Mn[ ԰g7YqqHfw>띖nF?o@|I 7+^9^~{Ӵթ.P Iw,9\#7O-lf/җI<{G3EIȵ׾5~;I(B`IN̪5 +ZphYyny +'uLz*ߏ3?m/ T7{S+qR,\o6N5~D?oMǶuT.{ oVyҸOq<z\`0WB7vMxN ڒy/.uf4^=͘URռrY`gŭ5JM0]'"5wjRb.qY&ۡ,@ +\5_!myeB*\;z~WBNC;~|׌fwF˒:0%JOz5LZ^W+^4vGgWLr/MSVeP泶r#;=j.ȕrYVg.ѨP kitao~v Ho[&Mݿ0תS4f<Z7lևKiɾwg{4`f?++dw]W+=3xOy/ұw]75;LO|w QZLRsٜ-\!ޥ}ۅy֜lN^8ۙgÒ\_11.T;sR<vׄ_7Ϫ Q5 9{[֋UNL.?wٱ7Gm6=ۜ=Q}6jct^%̡Sg2/hZ7/ ]/P{ÛG7Y{ufw.8=ZݯjCfI߉J9vc/Ӂ5f,6%FcDN1 pXYvMLYJv.b,7O!&CÄL65pKn32*vŸwêo<^(b1#Z3 ߠy)gg}o 42wT`4[fHGoݝzO>{qh]=f/nW}=v34/ٱɕ7jex׮Wk43}]{_ڢTе]di65{/TxFny¶[=˜Cw\+vz֟O-w>c +RW _IM=d+vaiwY%vxt:i( 5J].z^ol~x.[rݫΰo\'x1?Usfh:V6)Gڢ/}~Ƚ㪅D5Avk]2#mN5i7M[)(Y_yi,ǃ->oxüi泤nΘ_ +_9TXnobus>Xcϰs'$Ԫ~e;V:ͽ盀S628ejWBb. Bc<:+ubqt硘K?q^Mz?'D5J,2nhc}h9}_}:dݷQeCGVqphr{n];o{\uވvg|RZ]W/g,,S)r9q S"kM5?u^"?XX{ib.ε,GXe[^t-$9>jr/y3Äht_,tzWJG'G/XWVio>NәFӥD;b*n2}(vuw#cV̙{S* h?lǾu?R}dFݗd~{NKk]"Py;৽"㒮_.g]NKnm<|6RS>vޭdaOU'$zaũehVcU#ߴ9ʪ=t_8)yAJypmNC2ߔ{~ǜJI֤+2oyK]g-?u.N4IE(m|n\e" sgWZgٖ0o\а '־{\ +-ܛ$K]?ޙ^߄"q[oH@Rl>x '/MZgF b[ܷRĨ}nIC&ɵ~UNWO|x^7F?$[sLoa U.>?䷹Kغ\;ån{gfN l-}IUk9W<\~g #vĉȪ_X8ѭ?]S^`9?ˬR |bi_N{ +f9}ƽZoV@ѱ +W2sڰo򼨌fghxԮa.k ~S0uTl@};kxt;0E^?t9amg-$>קKga䭗8KGOᭋ/jY.6Q ͷ! akyCݟ&^8=k7[:6io~xf7n{`]ǿ/<|[@;djǖMiۋzgqR{jүHcΣvQi&_0bPIyWװvą +.&Owx&\6%7W\BXVv;>ńT +ֳ1}a+t^|7sU럩\I;Xƃ Oޔ6X䫒|۸,6 _?S-kR|eحݞu/;YwQ]mݤK2Mw#ݙB=;0zr|?$o=t4vo|˦{$e4tIwSdgsˮNzBMe,pQlv]=z"m8!Ӓgu)7dx\ϳӿvQośÏW?1b޷򩩺ú|m'zn_mRKUkbXf+w_$oi@m\%͗I=ϙw!י4MhOKVc/[:'=Nk8y޵2V?KX*oOۿKCTE>yWhZTכ[ZV{%'ݰˌW "Ԛ`φ°XYw"dPM׿6שI0m'W6?~}ZRsSm\&ЫK0=u}{Q);悵K[~ |K~~7.Îna/TFU/Ӻ\iŲWk{?<60i@^za7ҥ{jrk+qGʈ[ӌmFi;K :1_rZk#<9ܿ7$A^+V~kl6gʹ]sa{x>xa Ż{N|QkvO,vnXeyvq}k [=b6b{}"E1(I3fʫDGN[{l׉W?aW%+)I|sF( +?Zqցk=y_je"ME{]yXwS1@nOrOjM}'}6s{mo֪U+yJ>,L/t*0Kcv[#*nO?Fn]E7OGW2=|8*hkIXֈMߦճY’_-L>V\xӃlTp%yNeD]Bh'0^ڼc}asQopzᒺf,Odin~ 7W44xrJ̻;Zj1t۷&߲w^owkW)p4:2+_xܵ O~X E//MnӸu}F'uMQ +ZGO콰Bj-_RwmwػhgٞWxrCR \nxvYwy#UI(>l]pC IP?v!ӌIwDŏ37&sWm!Ɗޑo]zp{]A +8}&0iE:+{Bo,OljrsX_GV9c4mpY Nh 8V׮芳ߝ4 +[#sJͣLWW.iI*ZLf:*wsCl^\~b[nGZf=gRB}j_艹 ^SY6Bx՟]Ls< `|AĕwRX{7߱Cm}m۸ߡX:xq OVu%8KlU{t.1ӏߋƯ'D?Uy3q1nk3}kkX|9G#^x6bkH9=uo}>,(1}j6- t9a 1'bW<_ݱARu5>B")3&߈qTjtIJ'EQW}VZ /Ac9g&Lo鴸(ύ6ջҶtޡwʕ'+'Γ8S2#@tᅉ S<ȿ]YSUg2E!\%!8h[5|VZ~χ#tٯm>Jzg"KMn6^Gs^{;s])WꐊQrvqcu.Or<|=Uk`Ov]M:n%*mk_r"?2;K_ܫ3C=KTu'fH^*7Ț>fwyǥ_}ʴw6zt~5-kM\׍7'\Y$|md]So\/b_/9~m &Ox˻jvS5]Ic:W7?7ۜ[Re g +ܹb"٭la^kۈZ{&'gco`7x۶<#rŇ Rys=*Ϯ~o;|~,'Mw T +ʸt:]hEֹYY?v:UQ-7LS}; .Di5QJr[2p?[u6)Zԑ JoiIy.?=gνwLӚ"w^ZϷsf75j;##C,kǶƪ3?׍R5;;>}j1yɘѦͻ\ᶰ7two;?ٺEџOTwO`J^Df+b ~H7۶4}KM'kXbo-&;ZGTU^ul]g~[-RE|_2:ne㺊%uӌ~>?p +oDxSLOM ukMLLH”dؗo֨moOyx+k߈nzG߳_f,/S.QWKfAnˑnd֢,]ykYro48??ge׿^xorB}rX_fpVJڶ{EfϒάۧQg-ξm9g';tlSSV6_t"_csk+u(ܮUZ-?sip5`'ƳkWn~Uv?gIX4GƓGJB +{iLMܟ$/N[ɑEߟHj*Лwx?ӕ>UDWpآV3#VM}+.֑STqkxAr4؞yò]dDݺ%5GT]H31dQUͿ銭9imevlu8qOfQqUb4 dv_.TʻZ$~Ƃ[ME瓦^ ?m2-?8R:uNn~Ѫfw^G,j+~O޵?x^lRLƓ+]%p&AXUW~w16n[b+ٕB)}?; +lyvkٗW~fh/纻.s`{3k^9g-Ϝ?lN~`>OiNrµ/1|u!+RwT >ؗUh5m [W-ϩ3.|>;EnƯ^jR8¥!!tEĒʁQJT>Vda3u߯^IgO.j;:9<?"MWZ8;s.)>/W^0|Cqj'mc46Fbٕ׳[zo)#4^ŗ::''OFi'w_9_#^?j՟<<맪gǢ&H$s+қv"X:O%]OYߗ\cPf*Î=xV?.LoL]GOJJMqءc'+{QAK^oMEmYSn2+r{nC ^8q_Sۄ -kj~%r/_M/|=acW,3.ahc3xK4_wMHUj~_O*fʋ'v/6rz%7foy1yʵzjfMK$XЁ,:%C㷷 Wf 9Ձ]׾O4{aet?sK4aڬdލfs.=&h)Q*i-LO:e1~}3o2ŻUJ 6`ɿvvݼd!|y¥)njl~fؽo=«ٮݰ== 堽 nꗞ)V49 +u܋ڧ\n$_$e%c[!%Um/Y;׆K?H}Zcʻ]|oI=ߓ{xcc,yx_gծMf-~a!{ӾJXfQ +fgC+L;ӯ|jOd;sJq*o9sekŜ}ىY :L{o~vKv(.15疮9 [횴`KRkEzLX4eL|sJwWw'%ɿ DO%d}Nҁ' * _>'hc Ae:үX=?~bzH%M6*Ż:)|M?32.& m|s4^~['}Mn?u$[Y~F)xx]+\OK_ +_.4ymI2tx/U2Yo,ӓθ}AYq{ Ԝ9~KKkL>s7iNJ-^~6R(qUy?N -N0[o[BqY72ںҾ':v/?rUL)iYڞ#5҇O^;غѪN-c-5Lw71f.]ruk{~{פ;m'>MRw˷?s|7x|ͥGkU2ؾ]]6j Ng=#ri/.*rj<~4__}԰v!Ma1}vOzӃS9 [q̇F7W0.\-,~O5:kNx|ssn-b?IOFt|z,D*MO[u;R]c'UٞW^f*R,.7f~{W[?9X8MϜVhw,6SU\^t̙9ߧo~a{f;M0#Nz-5Bݽ~m!_JdUg pJw<ͽNH(k^ +mxl䎱旚z?씃|qJMY_l+6+}IߪxPջEi/-sb֙ε/\|y!gˮ.J7Ao+W_$vi;njcQn)L7yܟ !ʗ~j J췞HR˕=F֦|<#xgD.\]&xs9G'Y$J<דϷ[>og%4)*ba<գWSHn1ܹO$g-yG3* =۾p뎓|3dHX%(p Q"W>f(U+vxJw +Œ5"|Bgm~c^7«.N jK6 ̮7gɔ})¬f׆S#<քm8 nKզK֯'X?eHM]E%/>625$+bZE\wUWn |(,%r͔cp"0GCE,łQ}.fzTLo_Mf_"F]ux9^OG55/8-1mH+¾Ln^IBNc:括MuT襜6Zt#}2fI^|3v[|êC tbL`wNmΌVd̸YlػWn1^a{~Asu',Y\1MO)gr68n& ⢽mTc޿ѕ˦(ZEENJ(7gG\ж:eT3g,ܾǙ3iL?{!pj|s҆L&^{R/gڰަW)0ѹWQ4S۞0j,8DJ z{+Y4}?<|ozh m>νr lٷL.N +5%KΜd.v`Slwqʼn~&nU3?s$VI +sv*Mztk%FG& +1jmo^$b+9b/4.Yk\1 7(uUgi|K³Ǐhd0Kޯw{x`DEWZ}vO;gsi[e͉6Qmr;" w.78Z#Mg@e: +^cxcģ:?Gc|a٩8GNⴋ6;cW1]1#UgWOz8"qy8gf}U%EckbmTxn"ay+:-GW[.w섒35_N礨{5ӂ5[O.ݼ'q͹uY;_|}YB}:Ŗu|s;moJg~:e}\ˌgi,(cYo3F~l7mMor|S$왳鎞W}ϲ/u%pme/<~<ˑ)<6-5.XQq{|wϛ&u/e+ ._Kha^4`Y^vД +N3)]8`{53.Uws;k5oYo|>[0˗ k&J }?-I'ۅ >[ɷzh襾WeSʞ˿Z_4GYNIߴޓhYS]k/_  +?).ws&D/taɍ{ +&'ObXoxW7;ţ:L]뤔 Y*Z3 o\~IQ|Ze9ל׆=K_jo5ߚ- vٰr#H1k|j*zw9cNV?[vBNA +'77)R_5KEG~\p|^3J'l!]]x%Oe}l>+=4n-}P"rk2=u]۪2}ajlNeB{į9cϻ|lYv`ΰs,1!^8"ova^Ms~ޗlY,ux4?j(Yrm+̃NǷI{}zXy׃or"vqX7iaN_LlQZĭ&Ζ Em҆"=֊^/%9郍y┴1&nԗ^Lq8ӛMּt󗯟Ö$y&k 26.:A$=*ݲּ86fXEVI e.kPQ߹\dqJ-LF{Q$e`}So}'yk#V <#5DIgӷ wfow3{IiLoUU_|s1.\5s_ԼKgWx]z7^uKi{rٹJu⒝Y_F-./S*;bmYbtI ._?zxWoff3E?m7NbM^piљ{+5l(7I>lǞwbF\djFM-o{=apvodn{Q^0K߬ q +tn:b +W˻p!8!2׻sEy}C(U-O;;ܘa[ɫ +/okUVQ;If-kӂ?Jc3?/q}β9ROE.5Ը$F_: :3/x7U7hsgmJ?Isҙ}~+/J 2VhZu4\k3kޭrtFLpbRe%mX|ålm߳\:G֔[q5wmmɫϾyN4o㸿3h7ʙ2`d +~׵\v\eأNuOHn OÍy5aGBWU6_|y-,= %Z\\&ijۍKSSp>g=?(W:9*BR?~乳bKKX;5鯉oMn_՛'u%ْBC_SwⳐUWd6֝~B&3v%t5{z,OGiaɶ-fR쌰(x⺯=uLmwzkwbȍ˗g]|}-A vގ9*\~ܾpϗޓ +z_<`a"`=f7{&x:Gao.ɳ_JDK&<.ؼǘkͼ)s) :_Йv:ܼj5 d┙'5I;T o w4jݮ#eFm8y}SZ|u{ƺWM8z7j> a}ߞmʯXt۶~k*:Cf\|g<Kk5(q[ g}S|yWslsP%铞K2k8X,mypmOZUִx}2T'5]yaEySuN%%:-^xܢ\-̋+Xչ*9XbCwմS.eqga/E-SgO1rmz?:sm˕ m?,.2}h|{&MQ;yxO[fs<uឝ6󢂜Ww7]w?2mkWܽҿrfZ.1,vG}e܈;smK_,+d_\>jѓ8Nk Oo9MUiWyt?yCķR ,=e[fѵ04\|mN7=u5I-?x>E5IRq/%U^w~lRӗJ~sW\URvC&ky:Yɿq)?6Un˜1ʲ=&|˝ɾvu Mԝm5>?N邷bX9~fy|Mmod|h#".L?7 lyߧ}4o)`&Ep\9cUѱsbȂ[JvSVl=?A(MLI5)r2?fw Lޜ{BJ%,+t8d^t6F=E1wpnSqͮϷnQ}0o AəwyَWJy2!ii^{Ks=L%:vz읳S ЭK 6U\֥^c_7797y"X/_i'x-~Dg,+Mmcd |ttwſكn*!`~ܕ2\{#>3m͎7RzYL \MIemDŽ]?\S⭔_;].~beU*z뿲P7!ogܫl^T^'\;/;(-cxvcʩ/{e\jhYmVcf+Gsv_Xmcu>|TM؛v8;)$ƅ'#`Յw{N +)g=jXSR/`OՒER5q\?invs]lKl/ob[Z}Tsקe/dZ=6lt;Ȟi/4&=ƱLF\BRs/\gwVenїSMSjOأ[T3({qF`bW?5_IE]bN~: =ޓptqSBy =wX@˥T4}Vɺ;&Ӈ 89/.fuUU43Zҏľ^56iw{[@ГSD_2[[@jφ(ߕEu1ILMN+{h,mR/yMvzq o2gVI]GUx,cߝ鿥β~z_p);SmÿctSM ʂB7[̀昖G 9@3Ob[^w𯞮eBfgNməwV/[^NWq}VzbR 4L-Sy?^/.Eb8ۗB<yLOyz)D+ּjJM[uU>+އL֊~Vz"m^Y}ѽ[iNֲ_J4c[%o;8~֊kj+q|eGٚ6&r 9lW9h۴ +RWg LXu85M-8sе2^&ĄV;gnɛqi2OqQǒR0kgj]㟗t8_٪Dz9ɞ->ϲ;uWv+=G~lz.fjPBAN ϭy'=X!~Ggp]W6KNcw裇HP(Bխɬ7^ۡ}A'7ڝvsl脙;@Ib>uuSgm=ɱlӌ 2Ϳ +RHNi>}yqE2=^/P.3C䷚̵w^),ªҡ!xy޿뻂-5ӹ}^D/K.Ggg3^|?bN{yz2M 2Y6ey+}]ɕ%ȨmjvMk4xۋ&sV1r2?}吠Y?<gFU?ܢi^kQ689-Inyz÷&]̴ ++_QU* r7,ݭq}ӏ͛x5IfEX3)<9u_peȚCWn-[7G51]Z?6'wLzvI٣*Y<~1hHs]ƁįwJ`DQ]募O=/.Qmf [ͮGx&2*kۖXL/Ωks;_kqԍxT%]}G2K|7Sh[? MkE'f1W^7X#mKlnW>9_?Yo'(hך~QF^q_wڛc&|o'_i{LL_?cͧF-嘓2BZ.~7l.Bn?S"Wuճuڠ }d=692;3׷A|]e{nڤ~45| OUQy̎GtG\(me ]߱q$m 뼖KyԽGdHl;cdUvo [p~۶w4'X&qYM ˿,qWr=s,=,wrt4k>?t}sc۽Wm]y.SkfwUW9|{ +%&9#9J~5VmuuSTʖ~z]tOFۋ/-=jC-']l o;Lg\43wi*6Vҧ.:ƦNz1$vq\]sj/~5t{٥[B-^m2eZ8%fo5O)sB959D=;0.{<]ϢǜJ wKԞ9;N]s][8um}k!mRu,y<(М+q~,t%F6mGzFWx>zͲ.3gL7>>R\Qŵ= !A==_93鷕V5o/zNo;mDך +j4V|[%1U-~Az7{T6myPRG+'&V8DT4&闄ggyӾs*|7hWJ0\t7GyM*_V4\-`ə-,q;s2l/}`q>g[쁳jo:-{kaٔ|IŢ{S=f4Ң8Yv.zwLcW\M;=ng;ƾdMy-w6ke,K="&s9^j<|"%.,B`WO|BUm žFu) +OֆjO +z +$.Yz!/epLu7[W?˵O|߷T>Vǵ~I?ޏWgh>{M3WyH4ˡh՜G93< L`˖dpIxWU=Ӻ~fC&_.>䛫w?+^,Խ3kQ K^8 Yreq-]soK7/4%o[Nٴz'(ޟ'P߽z ]eF/I/`?ϱ`oGW3ftߨ#۷_'E?Oh~U/g1pM}OƟ='+<]'M{ƹ/~:S·D~U~^v{?ENL;y 3Cqȉ6O\%0%Rx)wR8쯼gKsݵ7'8殄ǽsOҥ4қ79ǸؼF<'tWn;}UGI~;}*yԃ>6rTk*Qso|ĸqu}w^ +IfV+j?:~!Y]GOl?=gfwPWS[Ͽ-,>^ꭣ s>S:֌eٷ<l=pӭ=W\kYDJ+~ahso_xqOձL/ft^\斥j{)yǔz\?}sL1׼s Kɯ{/ r̲uD?|ӕƫoޑuc^[;ʍt*_)魛k!W{gh]Hpnُ~mUְoLD^g;'LwĩY.^`lw_YvRע Nh]xJ cY ^cJ{ӖHf̺;;tGWV"TUiitC"]uS t;' qe9߾d:-\%a>)gt{Q| 3- _׻wÇ d=-rSs1]+*ZQ]}1Vm}J($~]8{fӣGU{*H.ط*COn?V䙂KWu|dIg\c=kU0~rh='c{.9޸u|Y]z]7|ޯKlR.(9^?w\:.H: n}&77nlYl\wߺi4xf(0'o\Kck}V~-l}Lo?h|'zM_0})c12gݥ54-:!\SN蝰:X^Ӯ{Vq^WkcLB-~aV6p!^3*JڰHC3cԨ@dc*[ͻŢikCgo+>.p}Zrzt 95n4Z)*iދ\='0uWXOrZ>Nw +5ۭ,BVa)ǯd[#:IitVSG? YWg|>TmkܱE;;V.xڽ%[|T +`ˆ77"T<Z{5=M{}7|INC< {w(OP%z!='O6mDrצ^wͿϾAfkM%LM˹ w=RV7Kv__ʆ2L-$,yEag?֧aunrWڳuBg%e}CL'[Ej&ξ?Ů;^VksܴujEܹLb9ˊktJ[3_VkL7/Z=caگx*1ro enN<&V495qj:yE0 /_;f=ˮ/^(MFʖ=-8o!̡&ӷ +4N9LNzbm7b_6]{oŪ^N%4j106>ttjLB`Wr63VWv Zޟ)B-Kk'J1nYK)oi¥. ׿nSmG}ǧ\2c_λ`DMفsW~Q`98ҺՍEɘ2,9o| r.U|=}8?+x&EgvSՈ{uy*ş\_/k +>K<p.~kS7ME/d5g/CKpsX%:%`|*/EQ.S}.$F. o[-+4O~9UNow?(7:'$fy6VW+l6dA.)7Ъ]ꦉQߪ-53+"AwT̝gNtFÂR;Fl=svffhb2,?<)h:8qUyỌvO;g?i`z{v?[$B俚zIZ7PKN5֜ShUXHdJNtZv2n UF6lOԴ u&t.t=^uwQڹFxߔnq9}]W:'UCоgjmf܎}xf{Y J,)u6*|Zpnӽu{fr.kN-q:?Wۀs!_^LI,V{IW"gOuXlՔc7/LiћUz~tVטC'b[ny;vPZ;7ӎvQ 6]P~7RGչGnHKug oˎ)e?eZ9$e3SsiͲe?iVA{# +N,:^myB<7EO0η\_0 JmN +_\/g)p]1$;lٓ&.+˱%OڜT=Ŝ?ϻG wkp_.wΕt.ScY6m'-?\߼ +,b"Mmj>%-(84c}rxOnzӑJ;D*T-?Vuߑg;asQ7ĻR'2_|o_Ln+<!~1bأ VP{I^0oڍߑ[†)mow??~Ǝ59y1l1m1 ^fuwƁug6isH|cz@A{w?ܔQ=9s±LMMGf{-}xWLO}MeZ<ӱ ˮ<._x8%WhU(u{SM,T٭Vs*((dwvEP{|6 :pstWh1Z/W>Gάoi/%,?Gבiy:vnn7fWؖC"3vFLVsnǧꆝ +nv\'N)9ާ4ek3WZuusa]oi('KrᡛGNMZ`OXaxQ2kK&[x02ㆀxsR'4Y77~~rN UNo[95TǏӖSJPIk|=0El}/e? |X?8X*?h^y G$tƜM.PKq;wùBQuѽ,E_:RÒogS +-YU%.>^AI|k?e\fwJh!C]jn 396:>vCw6k%+Lt6R8TAʏ>-g/>8wU'"Jowwr[ hY3˵fMX$P__.$xڷyC{Oԭ[N5u84d두)z.,Yuu֋Y gT?Z%ZBFV kc2ԞUs93M[ +^pu'=M7l] -VR?y뎣K7)5AŴS|iާIڿ=v̭on7'דuOJXC̺ +ޓKDC }^XaʻQ%gzߘFۖٛ7yᢃJfOL5'ݬSn5q<63E T4.kdѵ3}`O_h|g]Z?53,dHr˫[fV{ ຎM |VVkcV|ya1đn&vmmoBqZ*VzSy՚['Ygۉ}vd_]K_z=rG-mϘۆ/6 >Z4;V yiF br*]X1+3=!&$kd$w:;V.␗g5v-<0aY en߰E]rT %>T6NzZ*Qx݌ P\G*܎H:CϜSK=y诸[{_Fb)Ҵ,k',{z{paӿm.>o(ze|O%\{xڡy~-1:tل'?`pNm;:~7z2gG?uW¥gH;|[W +l'_?˯![hn̜6vnx\*9Lp?8۶bsw>*._⼤ܾJ*_޸ǹ ;;esYW\WƖ%<9%[d Xʓ$NhҦ ߯4$x:0xʲ}?q%fY ~>c/\iUBQddMO`Ս֓S4Xw=cZ浞Pxt#)þ?qQ]{+V[[V2ئ/(Ӟm3]by%:aeiIfOo{|CDĽ=^F pn*7|[Ƿnd"$CL wQ4›3']lgs;S}~/+pS[?Vʩ +?%g's⫦GMgbqR߉{3~-qb =$Buz>J%m0[mKGކc 9/l۶|l^_T~zz8vnbweY}pfJw .vK^M~G`K6=*+]r11@Nk. +q-`o,-\>/Iy!!gƎw٦ͿEm]RAZ'^}zK\%QG|l |ۤzGά7=qrx"zcv TN[nx>-<OwJþS| ye͍߆mv~ν>yFsm}37lȪ?TW~u֭_m&2/ittM/2uvM_.*꒺}4^^`zc m'S웅..I/|?߹}ߴ~(ŷ5ͧWK.)4;/>侭t{*GO7KKF5T[ +ۊ_VvrV+17ko?pC=tsܶpܔ~uIǃx8bʯeYuS(νݛ?/%;^{ۍE)SgN;1m_x܊)cчMyIБ o+QZTw +Gޞ{Z-yhxYۢSײ߷MXZ}1on|~ZTM:۶vn5(5昤9勻v/,`ܵ`Kh#MM|oq =Y߽4qyQ@o큉3&&\RƸ۪ysn[^{vuk,m'SSrP5Z7#_3u~ƆmތoPw{.{?p[ڴzt(yNgoMV0]2ӼLk wR|+O>{{Jq ++K'^+Z&[]v|ĊF&\-Yk_Hw:lyLF-,|>f)KF+#uu`Ӻ.ݟxR{\[V_[;\?Rk__93KON?uO[ocNڗ^_M::\w+-7?<},Bz̫։.6 ?wᒲL)?*{3!tݾs;LNJ=Tӧw9ƗmRMG>-;JOo,zX~4h'%-qVق濨u}umiS#^zT;55PE~VED%_XؾO\/3 +KzHsjRJζ-=T +c~`=[۬[Z6KlcW\-Gdhԑ5NW8ɡƺڿڝRi~*pٵףbkg}q]hI<Ә,O?'KhoHγNﹹ-w4+9ǝ'+ +lzEEi|ml:oA y|6XS f%~$. 322\azRUK$wSz]ispB{&_h,]n:V-e%\ +$DzKjzC^Y_z5w1kqUupQˆצgm:PyE;ҳ'ߘfͻ6EP=ҢXٸWYF#1/âuMRιSM^õ`͏7mbU|ԩq9]YCMor<]>E}≰9 +k9_xGpeLɜ{?w`䠯 v$@MIqqMN1w9|O޷W㖃ղ͏K]J|qⱔtwW.<^Vbm|_y{3t19bI.']({;ǜ 3?EQ1W/X^GSʙ7S}(vp\k9|v/dPqF' m!wqeW︭{۸]r9A3خ'XTw[4UutwL&{qJ`kR/4}[m??ļoWY$l[*s~&Oͺͧ?P>%7 _ؙܳzt9cpesJ/d8$?K$2$>|iUf.rOnZW䧭il-ILt{V8h#xxOhsLtyj'&:j_̬2o-X&RȮ}dY]6vJۺ~buZuz95y3rՃnY_[c3OuOͯϹg|KGS>0cf/Pv~݁FGHHz>6sa&sXV2uP3DX33-ʸrv);,;h[]3,I^p7H~M[rnْۯ9zmD"Jc/-uv"}׷2?VCr]g\Y~-% Y4>13v˄dw@emvl<҄~|*D[f]aɽTjW8p߸jkN|J֪RSi7g9?u[·嘦<._d:R~/j6G_sM|Y/0`=ʙų{LGP[ȵ:7}Flf{VxfK;,ZΞ(xj adO>oEԷ,S+dSC'}"Oo.ӳ_ܳmbҭvLrԨ ~mA?Ydũ;녌xcbwcU,Y^xX•'V3ls+ԣBR7|MM-#|&R.}zB5M;#W.iTfRDӭA"&\pꠠkGON˳lx%e׋'69q2sn9N\zaoE֘힬f_hMD]hڷKW3ΆhRy>o}/ϒ3b&6Ᶎ˻7<]όj^prM[nVn9Y/ǤnڰC/4؉mb4Ƃ|#"nvM + u[='D WȪo + +ߣ-Pw9+}Y;?hkWO sJda;Ǐ_Oyb5[QoЧw· 2IiOXՄܭ>ݤ9"jOZloSYmy&f+θnCwtcS_&ݮAUU-ſگ_9pɖmv7^sk9مQ=%?߷qJ@av?+'Ypj +!^,ޛpuwϝ.ȗVճm6iϬZ;-O:ܐwļ'VMͻռpݐy Vە,eýwn羂gb~K]+ѷ>;D^Sq̬Pͥݽ.xYeW[i";M/uYSɊӚ$qg,͊3/_>+InL6)zfP<&ۂkj[6*.N}Wǭ 則'n :#ٰ~֫}ŧoO+?z/bo"6[^u6H$^gg9oŖα"e唗K +X&'_`tXC[_9D応HX˟q/%?n:!cDI߼>21牿NLk-u+:` +T/OҔg}rs"432Uj*-ŏv.aYk:=Qw+[,qvYޖre0!ZFXz悜'Ol랠5GN7型zq؍lew'T]~6- +0 r_N+Z +n;,R%x 3?qmrҩKXiWd&%w'L~[n x'W7\s/9-r.Qޭߛn٥CΛm~jcu;LsUGz}Բ%=N.P̰z wT誹uۼ޻~UŔY镀Փ7= I4^8ks+?ryZU8{aؙ2!7!q-s>>'88xnAF7&-t_]kL5lڄ~6u'Hw^ox*,DeHU/Ʃ?,^nott/}ŹL1-Qu:=K!}&}W,,x)نZU[Rw/m=P6F9M\`u7^Uaubm=bzMwoo\pq{s\^,xkkwQuE$5wwْ5/8⳱Pwn,c`'}S -ܝw.n&[X "^;k2~A^y։,*SIhfryV;OkozPL)gh=Oζϭ2> +kV <0g#gAo[];y4}٭Vx%Y-*p1=R8=svl1u{9;9҅C=Ze>`)w\xuU3u?\?+uLw6wLW|p{n+ۘ<,yii!kxO=#sݾx.Z?Һ̖T鉨{s~܃--t\\Sg;PTMoDo^ęWz{N~}]*ۿ}/V/~?}lvEo~NDo)J].ǎX{U{5fZ+  ϗTm)ݻdyՠe +N-kg:f^Zs͙w%.MRF|V/1F^hײӼmQns2d8N]$V "WV#bl{~3wkI\Lm=Ee8VEJ2Y,Ҫv~!;*>U7- ϵJg ҵ~'/u=ٝV{NyB$O#'4߭lb{'U-d#dN\{tYwcl/fԭ|uHçS`ϱUe ^8MGyo2Y9_b"Ys3tu/ib:|G\|.؅+6{$k0RXg w7=(lܻ&>1A)pbWoH_u5&릪]tm7A0*sD.'|=!ctƉO7N_zQSV\o+̵;zB=5l>I}f`5ƈW}vwsl['H|PddWNCxȮɩNiWrܴݞ! +&T'Iy)k{?.vY焬>YۃOZYsKOO>#=ˮNfҭyAoZREmϙ];lqNʇn3 +3?,WzsۇLo#x衵|O R?(\{hJw~l{5Ojȧʍ';pqlsfZD s*a>jӏލZ(/;ϩe;&& +T$xz=Tkµ% uԵu6cڪ#to׹'L O}y{ +n; +<ɖ(O^ý9/DڽRݚ~4.foHZj y+t]d4 +c3؊Tt[{ gjyM7^ލ=rzN/VXo)[IR6~=:cHӉ7W +I|h?}6yE@UY-k7n`?cFqEEֲzVںA: _~2bRyװT0fseGnH|HXۏ9 ReQY2>ln'zm)z0Cݕvk>[0:bݒ̞> cPy-[\9X'콨O9<-DXFz-IKunW9,g%g]'/sK۽ɾ` +ff^(+uNxzg ߿ϜbwʷZ)ƶΦb%^q݅ ۏ>~hw\扵|UaI-ޞ/s83FK#%ΛpyMݦFz;9owݖx%"N\s>I4`mlj}Z:W_fU~aŁt֔Mo +/ڲ-bR/l`~$ ޹ :Ih|Qvm>vkWx?r^t2c2)3}y7ֈW,MBm-jY(iV^Ck&J@Qk +MWx/Y޺W7օb̫f,(-Yemwmaz0-l ӍY&v֪A8Vߚ,>yC.2>]xm\c~|fpc/ϳk}>./T㞾6;wzvHu8gM ^_p% 0  ;=(UZwϳ\?6Z$W`ϼK&X[|pV߽nHmlƛ}4w(hӿ}zy#r\n{?F͖Ûiʴ3ŦwuywT r8TYo>0a +.w[:n2=azFLz+TT%{6SV,}db՟y%ay×pkkvq^!wKGKWzsA-2q_T;%شRʗCn|crף=/X8a2V$Yh Z`l?طŤ/]e;}4+2 +p.SgKk7..طUklXmh'gP俾wczfvRJYX?|'ØÛWάM pM?IMQ9|`R FrKyeL9[Uk箘׼/vP󢮀oxqѻv;kQ7aa<ے%t5Kݏ-ό.j|Nt[gIoO.q܊_(3ޜ3]弖^3i;>Lo7Y=IZ}ծ+~dܙtY2/>R~ś0ͯc_5?7+jQCcV=oFYb/Xc5荵7ٯO=i_37];ڿz}*{*W2;vQ7"x8%o}u`Yl1ҏ +|&l6 _澲~.a{qo6t[ߩu׉G3<^uG \AU.R}}!ƥ lfIJ=RK)#eyv:>13E_2m򱮂ZEǟ<~W)hՇ8﷏y9GT?ˆOW!KQv OzN IF? lY{ڱ <\zԕ9>[}B?fdCWw[[&X`V % i9ltъzy#jZ~P:{t69xP,4i?+yLA]1.:PoNv:xA`tղl~_O qzӳe!Vɣ/,xRS?᳹r 2m)ls}Uy* O^ڞyUuBk̞^{=_b1+_p|*|5d6YX'ݨVqM'ڷ'wB5J3-4WVwJXܓr7><_tCdFľ9-&ﲠM;ǭfKf,Gumߔ̺f.+O]+(6w̬[|Γ\yY뤸?DxΉSp"7}+rr:g6Pia6>8:% ^mjƺhݷu[=Y'?@enUtMrS}kǣY.>iV+xg.|쎙_#&?Ǯ0܏Ciٜo?MKʾ/Ջ*wC4Gz̚EO|z)_Dْ7Swj|} ~Kwk?w?pZBemOl7i)㪴z9㫧'E?|}yA/7-pQQ_-7Yze J;M9ib!eb-fH&So~sj-ZxC.W.s%k~1LXwSsBuRS."A dSM+/tva/2{.˽&GOkסN446ԓV}\ֶWso{b] +?\quc./6-&'E8w1ㇺ,Otu\C+O]BZ`GBYGom~75g\_es0hݦ7ѣ))׳%8<~e:&jphVy5>DX}jr>5f5?NURw|}7wkGHhUPWf;Qm_87uAE "\/sZV!'a {uY7l|UuWxЁk )zwtAz7Ϝe3\rMzV3FKC֘k7pPCtz_yB5=[J7R\}%2YZ2K1ߩ<]j64=~?tMsf1Z]pLJ?ìOD +ohrsfos׳)lO**D^KM8O1<!Q -kv}/$?{-lWnYvחw ֭=W2qʭ[o~^%f w!BhS2?3Zة>]Mi׼zwm;sluʍ{7)e 3~YpqV1%Uŝe w[(`EQg%y#ӊ _pO׾ʟfqPsa둺ڙϮo;u//Sn-/?*jmd{{vh^nRV|=REdR[F*;Nb O6GM">^\gJEY8[sE1*nז,D$SI_(;jP9-yU3{E_m}%b+ߟx*ߓNf=wRG +Sή"3ZKn\+>_'Zpկ3O]k}9ߓ~YP!kdy'_j_{?"04_A.SkG-3:Re'xaIj3Kf~^zBߓSqX^LM{6a\z%Nm^/,`|Bb}gfsnR,75zI^oSSv  4߹Gs9\0s9vL5w׿%AuuW1)8fHM%H<ՆyTRoݛI~tZVYna渘˪:Į.o/Zzd)y[:=?{֣":UJ.s럫^7\@*twPijS\T2o +wx?3I,wuhGs)~o+ )˨=X8pQsWҾ+-]Rڋolg3?.V\}u+3ӯ|$0gUѵ7;HZ x乿Y/wYüƠ[<+{Kïߊ%z|-抝iӰq璅gijo^6e͞78{n:sLmolc煙S SQi3Zylq۵l2*arΈߑy-3M[6f']إ{I`U'?-l8_+1<[O8,Ͼ6jc7dg &k;]w7N75kʸWYVng90k*V?}M~!c;#,MH'~ywwaHVĢ 5Sȶn*<6Q^}t,Z)mr=%93}з&gީNjY½8o4nPv&Ygbo片rc-mmV}2KezbJT+}gZz과s'dX,Х-nZyv':.˻k~mԴY҃ҪՕFV+v .yʒ},γr^|"7OY,`R}+W}y3UϦu>]ykڷҢm[Jb:?ٿaT1#5oܟcfE mLR|зߧ5yMMy6kN~^=y꽻ce9 PVvd6Sa󊹫ηIrS(y[[g-UR-:qA}~PtVwG+^ZWժJ_RqgN\,]t.!cb_ukK҅IZ;w3YΫnS>rᩌkRǤ?hʡ]:lOV,{źkO$2Y賞ՍQ^rʋmܺg0E'>gYU7bҲONU3uG8fY:Qx}o"kn_Е'^d5[S/7 7敯\Ff"˧m2‰,% ;}8.<~0RӃ=O۷ydoy3@(ucf +<Ш>Ձ,`Ϣ<FzRt_Ӄv/8ã˾]O@>yryKNv*ɺ:f햑r.r9C6<_t/?oS+wO9LM;͏4 _oDL$ەJs7r3M v'r܆r|(Z{jqSbo ޟmxZة_xxK;.MwLA9S/KuF<9ugAuNW?+m=^*Mx}'ulJ_?pł63pd1|!]Ƥ_0\7[xm}[v] ˼'licUcʼ|1 ,^|9٢[=ZGgfig'&] ɜ4ii7t=08Ym`^ymy-k19;Ph}q?}xi]ʿo,z·V>蟵ʙ;uH}A{kәN?w AcWK:]0[pQIObVg%\<*o:ХƗ瞖R;mT`ZWHqUbTs?RzK;WzWKRХbt_\^(>`eW+mwٳ>G}24IwScםrdSI@,WCuov~t3>[sin[OUJw4A+B78d)9w-묽T}뾧)`A%5]LXr'5[6m_obkE&v/s@[KN[sZfvMfzwjc]igㅗrY[/9*ɞmpy+S[49Lb{K3<㎝^N^]&~k~"6YB/ȃIo\gW'hx^uSbvykqY+xRTJԽ$$K/Ľ`EOD孧h=IYCl~*>l瓢gpdĄgU7<2(i5)]}9;=}|OQxoaf߫:> }^ΕigW0F8Hl*k١V' +^q;aU]1VRs=[3u}?% gyg'|GsV\@--TRp"ޔqĔk* kl(1yEFgwqι+^!:)|gz߱zrV׍e:YOz3J`* w?7;NNٕy)#v?I7Vr?=rjo~s>}&[kD>`U=쁠=kNKɹ,v\sw_ueWN:xjs>>\yWf=>qfm螐[sx]J/\f%=E33oHi>V!EEE&Yz/L.w}ǒvOᵺR]dE|LOo-To5[*yƋTטi`p9?` +Ks2M=S>9wOIȪOνn;hhvnxwz㕫<:2B!3ژ,jNJh۶}mķ:#BˮO_h}}^b̡G=n9I爵\["2mlc;\2K+1BaJ"_2fXT)F)S,C1 +ǽSlU޷e-o,н0}{:P(}MO/Lnc%Z?8sXCvQBFkUa%c +cN^{~u끾ל +D>NR.8 υ2W>I2k_>NՂ[K/f ["cZNg'u P>:kvoֲM=ǎLLʫZV7㽶K۵O^ME.Vr0+JSsn@^ ?,<}?ُ\Ѹv8QX^m.(-ehVO&xW%=Uyosi7VoTh8e܊o^k63Jgt ]- +Yξ>ѐt:q_|{j}{>s_XuIr5nR pƩ5V/-h^mbIw>}qy泗jla~ۉKY׮:em:^@Pw/J-\Acoǫ wlZ*wo_޴eM b[{ttnnUQgΫWj5=rau%Sϥ|VUqbXժE{s/.f%!x"s֎؜6ikuI=1c}҇,/[?GNrN9{^(O~wۣG">*iI?( xVx>-}wcWzon0d[yg,m?sW絚BW\fWz|*{idco3&S*$N\ؼAGOޖE/rsV[&)"a%>7MVz4M{&°Wo3u?{iOЍ\sY=WnTݘvN55|ŽQCS6 :*Og8I’ÇcsOuw0~󫝝񚷙/̪)ً/oy4c%߄Ō!A[(.-/XkN<*';=Y|5yH%+dd=)pʆ7|~u,˫\t)Ŏ7J^9v!fSTwM.{gOk=ֽOݖ/lJH/6Q0m/4-qUr g3u_ګbyKrC/ʽc=R?lsyo縒E.ʳ¿i&\w׿P_{[F0SN8տK%N4{>}R=SINy`|$GTm,~{M"b+!vi gNctx;E/ӷ'):_iݟ| F1dhT(̑8DJ/cN>3lIFs̫d^nt^XL/}lcߧk}\ Z_ZsNޚZt%l6kmŹW:eRN\{iП>k 6jٹ@*}"0WQ3/uVw\EϝOLV;}^U9/K AG5fL{yuT+MV-gx=W-kz:Cڏ Aa =7ZW]p-l|'_g橶杷JLyk/ g]1*x[9vLݛ?YϲJg7xhv1o&Qa[HԢ2=+%rmxEw;tvL gi^-}rђ?4?ܫ%~xد|upYO;DŽyK[%7=dtܓ#jMŋDdyW~2\[b&rSrOX3wš 3|ga4y/%9&jx(ߴ4w5Ŷg,mS'¨JDw%<>+]vI=Ou8Pǭx}2%I%,Sʽ6ߝΊwotwoLb}yvM_omUe:}&K5&5-nJ\n;Na40{|R6l2M[ZL~scUܓ{.~~\w(P8v̕'9]0xwUZKكOa9__xoSX#7k<>/]4Kt-^ٺ:.Oד5fmQreڢ\ M8dwiټ>fNJOݸhU*ƶ_O\z)峴#>Mw߼q'DKhmzgKbJO?f$¼g9#9 9cbɕm9C"\gt}qt濛ϗsdKem]*eQ|텋0>%31Wa<\sӼSn}߼;Z=gP3s_OX'jvT 勶Oė'Ut?}sY-œ4^ +ek>y$d]''ZUߺEy݌_=ͣElx5w)s}Z ݭ}K-I^>:R4CN^ Gg/o/4/ 0/›^>U}i:ca_4)oZMIa}|˞/xn_m[B{.m/b{_6K'0k[}֫>q Wx4Wmg|kd:>|R# +&:>BFW<Լg0h_):3=D9EH*4c߷%i7޳xx2_՞+5pv|Cٮpqh F\(Zzww?l׾~KdRWuMAp*Iw-̯|=ÿWlI;7ly~>q U>f})|k DDzkW56-տDj7lY?e(4GK}>}K{=b}I$bB=jNŰI-+_kkl,ex}w%/8<~聝j~u{yJmoX {ܽwopUs<דW8&ty[a&YDkYta{_&V<[@V/RT9uKRjɜaP#ч˯io\P?N'X,zۤ[w:lS zSE\,;]Uo-qar״Jzw,l.Si/m%'п=&\ds.Qφ; +Kx^{e*ƻ< +ۡ83Y;gvG&VW+~&.=wcw8si _~fiw9Om(kK]޽bw]Ykb+JM>&>~_}iܯwqg]wxr2[7)*\ziE]+\u}o~-b>ܬaoHSqȮS5>Ӥ\$M\p{BG#keic7Ew售诖R`-r6cӯ|t|)XkйUw. kf|akΟog?}qun_4lfvKd~sg"/`>u +[^&n 7]M&(Я%PjweWwބMve ;k8I_:v'),u^&n٩=N;8%HQj3w+s¶qnSumi|q{T,msa㘃1לdg^^蛜7W8;)8yMtuֹo,l26?SEw2WIvɡaB'~լm`MST׽6-zasNa=+hxk$X*H&ޚj_M<'K:i|& n +ORa|yo5F8eV/}hb\w"ʻymZsgm9jѼ =„?d{rϼtu=gδ7e=q&L괝/eϾPtYϕ<:U~g/8ݝ綏_ߺ]>{/}SRQcLrev{> hϴseioDTg{Lw}S>`u|y L{PTn[טGVOO-63Cg?76H/ b̐%[^4ysӏD_lۮ:5uם(."qJk\{٭Z5ۇ,!^*ٱVEUϣc{6z}X+;Á+Dl Hڲ*ִ%e:;x=sLOϸ +7&*/Y9W3k:_lWuztr[˧'y[|ƶ?^+}B<]SuVn2O(\I=_K4tf]cW + yOMĴ?/>gqL76]Ӳhf\t#[cDs-NaSbwyP+_[~=Zȩ}Crf+yK[-}ʁjKy+^]yfj['[EktY{{c7ߊܼ~vꑴ3n(8`iG/L=S7"w-hJ^kZAQ2dtHxO7Ϝ3,2'EtgYv}{kֈǹnꐚVMD⟴KO c"7+>=,>{c-¿/=4[:&z'rز'-Z(qо4DNDvߗ+qklVӹ^;f~,ߧ `£6n; X?ӗ:vE} +=+cGFEo[jި?n̓uns?-^})[oq O"\R5UK&]m}pMrj>,2v+uo:obtBt]s M"YwY}`N̏w>hE/ZO8v#EȔ ÃnݺCHc,bo2MS|t¶]|]UVWTYzjAXOĬݲi6ϔǦ(9Z2w'&_ _¨M{uei[NΗfXA"[So&DWy EE 68H$j K?c^ڲ:ʶ7Mʔ2RkYړ߳Tg{;(Vlڻ=E.?=yڢoT0 hqx\遯_G8Ylт_fn <κz?Y#>/+6=oߔ󯸗GK\l|Sd}oF WoL?naӳ;|nzʹ4r+[<9;yn)Ni]ei>93|J^<.sX9ڝbK*v1M5{Y_b㉎@_U8j5.l5<_ WJ*%Ts~G/'On9bmΜn?Ù -n_;Ǯ=tv ?_ZYۻvv$o-~+~{q敟J7+c_޲wˉK|{7<L?q>l3eGjϹ.OSf_Y,7;}s`~Eck rTm&S՛{l{;5퓻ܬ}^ +7yvϷ]>{ίJ;xkH/N+(dBۘ@ X12@r2o"H y<>Maeκ_w^|;5Bz͌^PZD`J;Koj߮uίʝ^j'Y >| +& V a57O);ˇԧۈ<͜yeTV; +9ʢvo+%lv[~훳Rv4py]ϱLw'M.|n/D~edqQS3W?o 92##WMbSBߴ'oܮwl.7839JNmTPKۦwZuӾ+ߜ-\gJzKKk>-~$z):ܐ2ݽo)Bg_hlڟr;~)ŻO.>e܇VZt:C{uk:O4 8"fpGڶnj&aӐymѫ-M~'Ӧ7C]gq{빴g_<{Ue7,0P/azqrsf~J=gtjUNt[-qbJBӧV/w*PأImO8%"|| ^w36D]_agkՄn:]zŒm9if-S^gח:,]*bl+ |v3";>%`Ңn7sNNf]tKHk+PZ8%>m`sx:ۧU[$xBC3ۢ%VK޳dΚS_ .(`f/:9yn=,Uޫپ!Q㓟1%t[mwҍ:5w} E)>*z35y,\"jG |sMo-}vMN,%ϯrr^Z1Vq˟eWx! ȸnji\??/~xՋ) +&oo¼uF} I~KYƪ!/Vsu-pӹ.)-,qFSQ?& mYy/Uq Z*- vn|?1ȩ>np޲zUm˖8`*;cզ2uBuN .I}?bo#-r_bG/Z/X &Em&[r xqop8£IfXxŇ}/i!Mulͷ묃;v_.6f?b/^Tg㕬ݻ2&K0_$aʓgp,gol#7/qPس4BxG/-Rx?*zSc]%*\H>K?8ɧcq?v\]E3?4gUc7^-ɗCxU;3m51U3_h\׭z$Cko뾹,,Hv՗/EI! >0}v;}E=M@pֳS_kgVyW~ 4nN) Q /3&9XRϯkk^Wey!5Us邟ܵ_\'xk}g^<Yjq{oQ\x̰LMZ# |hȏ}rOg5dyBP@j\U!͊= %jKJ{?5˧+.,/Y H=mv<6zvLid竉{EXΙwW-psFWћN'|?gԱ^_jfRΠƓ^:N)|8H닜7n +O/N_hawdi-Wʻ*wҧ?o)}c 'uzw7zA7nt>FQŕ#Ξ@Z?յO7m]jzΗW/ :*A7仹:'j?tZYͷkܴU=L+P{|䱵օ<\}|ry;2j˄깣q{ҁU̝ۚRE-dm*9ܻfBӺ[MMpu޷rK/^pBt%^с'8xۦ1Y=A[Ļ:]3?h[z/'r}8]f^[0>Rojվb2KoR^!/ud,ۯ-bw#q0ɻ1`^4%/9y@FK}p/>)gڤf3ﱭ?;z46-}Dz8~zIs}&?i:_դ)':3*!mOU=z֫N̝o4xLu,5{Td^!TNZ=f-K;y̾1~JQsSx"jƲuwB7*P:~LtWζ;.[sNKyVoxT|Da2Ic/\:&D2N)z~{Uw:gXQWO+Y̾FS8. N3Q>ϕPm>);.\ *H[X~ʹCD/sWb2l׺E[?vO~w&/o&9{hz[]2i6*M^V$iDz<u/`m:Aꞑܸo.?eVӶG^7rB!į7-c^"P--c{:|>K_2NXp|Pzeرk;N:ma:YL7pi}RtR9?(o=)s_ԛȤ/%<\}K8+g&J+hϾTuڳ5%WMX'wlk:3a23' T 9UFӭ*wÎ8#oUYY^_欬z‹ܼ:Yt]5v)_*n/w.oYwVۜVl]߶ܮ :_\({Ư?v5=PyỶPY0t5.SeWPY҉]Y]ݿ":[Gˊ3 (5w~t.&jտ~.ܸ*9',oDZnb[b{PW7#u3-\ׄ_x϶Xq%#t]˹s={ vՋf~z0{*/Rykf=?oڤYEҚg5\藖tufN/$*"̦ݧзJN3՞ 4GQ +lqAmۓ;3>Nim"7Wr)pۺΐߊ',tΛyVsy*|34wTֿQ/N+?Gʤ {BU Lb[T71dzJ9/S"{lԜ{ٙY2L}__[}K4 q^3 W>y-kճ6fQeӥ+*J۝{q~SK##5LLia{y&C3doN9׹n;Tx=jcg,c潜-'-h=UEgN(F*^}=6۟Wκ6kLjIuZ7_M8pK6{Kܵfn3?.%'__O۶B=lC]YY,v=])|. .T_\{=rJiYr5t 7'~(zJ /X*\3eϞB +b8&<:6l?΃wZI(2Ԯѫ!)Eϖ.;z]sƺBEiKX. 팚c\D0^a5bn6W-V{Jj R}K +r]}u3$rb&faַ}=T:mrGƬ樓q,(%e"zӝ>\ r^hO'ǟl4Ic1Wۥ,޲s.{a(:W|ѝ팆n5d:rFkDz𷊥w+Ny_8⛳jUvnVd~?fLhˤb_6jaV玦Z^YZ;Y0Ċ۾'Cv_NqafPsS^_[`#>u_3퓟ӽ6fkx3֫9~n}ku޻IJ!>m{_&2OE{w ވ.8.7 -%sSծW7}l)=kw0t?z[%QxJJ+l%S]1fO{&ٹ(ӑی:;,Xw_64S%.2n+iQϚyD7.CB,(ڧi_ݗP5<魋 +V% +\tp;~rL͝b7-?qݠSH\%<(#U꺤RӾdӗu{{o,aTqQ?y%MjȑtgK$& +RceƎ.dmaZ듭6<_|Lsfdύǖg1~5ȩ3 \vARտ|Ef%f 89iWLי9\<'VEm '5.3ҿٲaIBl*Z~Tշՙ6=)gժ#?Q-Ŧ]?uNzpWd6m?aiT~E~R,ٰ[_MZr?]vm\N&C/ORYeV#.U@/Ϸuk$>99դ.F[0z3E.uQyiY>//_+[Bjt[s~7*D`\:Өz +mrչ{I ,zedꤲGJU%m ܵ(sU*/978x/|IҞ5o#GJ46f%^Ew>8-so{ހ7I:/g7y`9[#U/7I>IMnԪ[\d:%ͤ<_yY&m>5KѱwR^oIder{bM +Xos]oYsy1}ffav _?%֚VXtAcCިˈ~ضNeQZCQ{/_qv9}rs/%:^I<_^'S_I`++s6i|FUWYYv싍}sRk~lk4 ~5ٻARTe;.lJKMr^:3oS_rhyOmǭ U 歈V߲uѵ37pYFs[K[2^Ҷ}ZfgؤDi<{5E2Wݛ*1kW>+Edϧ̆_Pٻ]џNn)|*. wĤGir.0/y,);n+6-sϽR'ݍxxIiu qYfѹTbMf(ś}kvV `Hĉ?YqsK6{K3R}x 3~> InH?wcĞj%cmo˺SO+ױ=|ԩ»IRl͸=El˳zooo5$pcusC7]sZ>ݻYmg;34@`c3*VJU=2~~vw wz)rɣe\~yr9֦5Nҭ^7cmE_%><_{^ե+g;×39tp]_v&袙^]ʍ{9#}6k56XDmBnqnn?'zPwkK/:o:?QS9DzL}\╲ԇn>5)H\볖tNXeGi> =ii]5b=gEBjOM >pMgMXe{_U5Cyó)z۴?6/ZsM?ǶژR󿬞,pB*iSwz׿-K-+ a2GcUDܸ9IY[|+mi-mzp^1wɉo/|iۄm'מ),z&6Y>|6yjO/!mv|,1~{k-bg-rYaq.mҕ>w\z.zQnNT +?rڹmOfdͭA/WY,susEy~g<}谞rjo< X[J&׻(?*{.b3I]A{‰6L[^mPM_VeT>ȲMk, s,lXnn|ђݏf*)px嶻>s]sflyNچK+e_Dتtdgq}3v)/s}ͯsWCN\KgM~+&y5?eUmm嫚Ƈny݃/YLDM?ĕ=|B459fƇ'3JЪ v_jQ}#ܷt(^}ʏWi%AL'xgI?9rß}³c;~bbTVWT6z7B>]7x&G+{jۏkv-^ȨjM[Wy * -]9z%܁LG23 *B_ca "M.ud\.ܹ" nIoܓSBY[CϫI?Mni擉)--"m2OӮLȴVn&W?^~pM{-V?׼ݍ}y_:R/Ot!Oxo?k.m35'|iy״MH$=霿JXLqO}(g^XYVwnɴ,&a\委\3y^IRr^N:*v'vuu{vߛbQ +?RJ~ηy[+D'7}ㅬb7;O f8 :aUB,M_037r^6hqYI7/'ʜ.9\x{o!39vZUmD҃Zk?ϗɬkƯ+ك% ܦ$vG@+ol;yqO@udM;:c:God?]ѣ*6%w_ܚy9slujVP` ϵ>x~@?X|hcs7>bV#M$<'6ミU=m9/sqvH%/\>KoqeYn:2_mۛwmf{[[[ybxV‡&7S\;<,%.x!i^3zg91~DwӼ(fN:{6N%^,lm ;f +#6}*r~^<`\/z _e(,`~h[94_bomu,OHqz;=+ttuu܅% +w]WMݛU_1gOղ"E;Y_?φJͬUS}2i`cdڹ/}N_ +5k3s +[~/Ey?~0%e˺%~/eaO}=~jgw9>'֡XZ~o}׉GRWh'i6oK_rGMuE9 +ɞRΣM="#sb`qx +D5g, 6*wC'Ӯ"efM o(rt +v'i&]j뢒^JkRpk|vv^>ۛV?皣$.]׻ɽxV,:9o.WXl{bߜWOhʵ}Kڽ|zG~foj}MR n']^iG υmSڸદx$![}mryZɢ+|[R6,]Ҕ&Z=lI}.ǻs/by[ܸMP:\Vl ߪL3T>fաY/>ͫiU!̝eUXٚ3S X Em/֣en/  мԬ{NSKgT~K>9_=v +*+Lk۵. f:`=sį%Z14=[ak~w V'K>tܽ\zñcz +9巙*D.W={eݵAna0Gʙ.r/D֝>~3CM*gow{Uݷ{J0ەe6Kf]V ek:8{c zl%{;6&qOԶY'e|~EhsmYoU -~L6+y=q d=YH`Ogkwqۣ|f}MYG_(Σ{d8Șyc +bO9*ZU̪,-RT"yοWIisylm{Vʿ',RuMEKk?EL8fr,ޣ@1Oނ=q} eƷ^gե*s%a4׊̦^51<_7mt[mϦimۍ~n y64qW݉LLzflZghiy7uay.5{۵^Ż&} RvYd&_ݠ;yJ79G]X^iTNfeSB:*`<7~ymZfNp+um]u[Hm=k|'F]îX%JV#|^ԱĺaG?P,4;4sgWr}}m,Fbۜm z:!^ͫY._$XBkK3ܺC۽:+T/ݩ}~'9H-cؙ bwe{S1ƻ6vty _e[ n|ZWxW]i(?0Dzvc+oy݋֩Z$;cV9"?<w;o*_^i(aQFPŗn/JzV߭Jz"?VtbVM~U|8H装ܿ/10*zK>Ek[ft]wFE'^ߕϳwxɀi=:< qn_qc¶~ {bvyaW`e 2뿝OzÊW"#TU2W_Zڌ2hmҗ[[qA\.;Pb +rG~g&>2 e;z'xƱ]KB|^_};ˈ}Wm-:Vij ko_]"-{_%kOBUɯ +lKrs|!ҟ M겜KjNN9UvK.Mg/;Yn f׍ eZ? G!+6}Y9׹vW*u1aOOg%5IhF [b܋[̌^tqѺ{ޛV\hY '74Z|x2'Kv?|pi֧mu_6v;K%/&z/ xܦ<+n6+)~!te[k oWR [)v6DKAwg5k=wx8?,mPr^w/TU%e\s=K*`֜r}wYz݇+iPݰoӪݛv8%.~a'C{n=I&B/&eȥ~McE_Հ+Gmnߒ>z_xCL*7.iss]CUO%fqUӂλg~ָJX=@dߛKNL|/q/z')PQ3;]oٿNx}Cҩ[20_;qے}1VjMxr f|m\oastϵ}pVޢv[&yoG֚Sw}#ٕrM/q_?ߑ!wy?5K]S֠%7M[bV.o>Y&A,3^bWMޟ|DNKs}"ùrբ9vO"6o>FwI(x{G᧿y^.ݛ}Vbf6i82iwb]}՞p4^QvE]Fq5'oeYTv<6E s^U }RDtݱc7Gq.|Zj3N"}=mmuKC4y:ٗqL]$}]Zꂸ-ozo yptyv?Mۻ7lpۭpISg׍3ҭܺ)?7{~q<|ݖrG7 [,bUߵ{m\jfw7s闁JUT>n#nsN;EߢSeE|.ceei ؔFߗ l=6l.# 0,~5ɚqηw0_ʩaBH2L:fGPC,s2g:0E_kPӋxd M<|wzGGΪ:}Θ.oT|'lO),!9fﮠ;Z6-M}&O0)^]O<%vd(&ݜK3"ڝ8^|p +{θ׊U͞Y8₯%=%ܡ|sgL =њtM2C/uմjY~Z+ߥܾ=-O.2eoEJ[/zO+R鬜wN=_oωs? OOc[1 ?E(*vi򂢈7 V^Y|sg7BmF\kaչ4-Z7'+xsuݣR-oPo2c5^O{GtsmaUvyzV?Y[o 7pH۩#0$_yz''Mg硶󪘴'ʹbW'DU|px{m7fNP3x~/7qewZ!+]O#nljv'?SgPi״-}i߸|q4ֺgptM2MpdOķgϿjl-X,R?\OҼטh|?g7nSkX%c3ʒkxO.y+:u?U}W'um-;adfwrV*[]䋍_gم52GVWpi՝jօ{IW2Ϭдcp Y?_ڱZtC7!w9nո`6) ,&ORhcd֤t.Kfee>z}ל+(Z<[>JV6A->|kNOOX5ӿsOQlV8{N#pc]X<>p/V$X$Z.?b-yOkQD]a޸ևc\)$ rǚ7u˞*xHcʵ9=-6fLV|׋J-p-rT^g>nisgHov7_՜bUuDa|v 7o/grL;l7-;ɪZVgY3-([5铿/JMX4Aެz]f KVMfQy<<*s +|PwgƮڃL/:4߁UŬƣ9~,%1F{̜N7mpȜwO wҁ7'XLҒ2way΅On]`zjGK}x3G"=S +KՏ<;Sws'Y[S{,=*pG|~w`b2zϓ_TvKRlaw>͓]߶֬Ӗ̐иQ^W`a쪞c\1*Jo,J*\yϢE5[윛=S޶SGK#k/yx5]Hs%[d[Z1)IJQgK#ˉ9J:o[w_+OLW~rZX;D<}sT?8cR.$#z9_?7u-Oﯻ=9{jТ_?Sv-"&zcc'3]`$\fyǭ:ѝdoݖPNT5[k$в~ʀ^ӥit咩;]9lgDmMt'Wȱ'c25nk|_ yL̽F`la٫>y6sߑJ[wl>6b?&7wla*wމuj͋<\0w]` U2Mu{I~UGE$.|yԯ{";sgçRgMڴ~}u:V^w 7_ğS2sVj|=)'}1?h;!fa?(i&P`=GOW^OjBs +EkE6tFߕmU-t=z巍2e{M{l3ӣk'˂n^M3c]Y[MXʢV2Ϟ'x풵{>K66.WJٜ.l}a/z8TD,~>_ +LeTf\4}Qĵs=,ۤ\u_@' c7ސf>UX37\,1@ }\T}ܳssĘZ7&ZY=7ɋ]f_=3Wxry+~!??v'ת_206qzt݉襩wMZpvʭg_IJګv< +HmioUfu +{ggb]RSY^Y͘|R[]^۟1*t\>Pd¹rCumɖvROhIRnu`l?#:.vzq|[3su{ݷfZ&`g QaSM8cיSz5+ch+4orQ=.uW]YznŹ6qӹHy?6nL"fϻ5SWujb?>ߥgZ\ +,^{v *KX\x NFp*9TGe%/?a]ױX&MY/.ӪӌH9Ww6^-i8-yV+V^[r~_4ѷȾ ^E7Zl^Ւnjמ|L+P\g9M>zGUOUٯܓay_Qz]log6KzZr8HEw'cI33s"Vƭz}gyk{,_raݕ'I^%\?!vϼ+_ylś?O|l*\LF痣+3>ݿighu$/CÏSl 0 gr&uIҪ\:7oJk/,.'[J|<~E6-ϗ(ȟܱqv1W\ȕ?lcF?hIy]۷E oW}); |k*ncg.h1K0sGߏm0иxK WŮRm??9GdBg=21x( =;Uo=OOWt'/WvПO!&IӖfj_P }b.ܭVe_.5_*Js]ڱ{Ǯ`S7#Ns9-uo\^='u3+V-y2b.u3-??S!ukmܚ$RVK}XWfw y[[vXkzϗVJ}g.k\`{Cӫa=)]EN/}2-?w]kq~p %VDh //}>铫_kýk~\WҜkɓ/-zw_;w%WavsAԽm7ݕR7i-&_JPֲle>oT}sEw)SxIn,CUŲꎖC3׺O|Y&YE[InhWhR[ɧve۟92|ڳycީz_qf9]%B>+wUj?KLU;^J樯ͅҼM|[ƤvߑU5ڪ[)&L go7 f_zf(-f^$+.)ZbNl~?]_orU=s]zs}ͺ =c̒Ӯ`T!19̬iO4֜{ w,]gUn;U 6-pUJ, +s'^Ґ~>Xe3%# k<\ğcE_Rk"eM9u'&W-~{Jɍ?L}h733O A[`=A/ZL%}+g3].*}2]Rޚ[`yyAXĜ΋ +0$WbNQ{Ex 7.дߗ"}oDac\"%l.믱[-pV߸7zqTuFǻiݙe|Bw =^gݯbRYO y}Ņyϵ\;k2yy=.\ \f3+~#v]PvmyQrZ]"~۰vg.mTpFYuP}1i#*u==OgI}t}|%AӘ?0eKmkv.}ς6k۽v{02b3fb˗ c ֖G|ljԵ׬y'duӥ.ޞryJz.~ !Oawx 8h1ZDj'y09>m +ݟ.}]je>tNOyxXȉ9;R8bRy2KAWbC*$*\.Ske|8%5zLcN*5Ygg|)J)̊I),6g<9qy聽xd~ϴ]yGBT5Se]b +Axk&RO<ī໙:nd~8'rP_gݿ}+SeojZٙߪywɯ2s)]Y)[E}6dV[6?{:;)l2[/GJ5m,sy?tZanoX8F?[H.nc:Mtg/=ri⠗5e+ޛt|9J&n'GV8;Ԝ!a<һUzB|eͨipFlX'i)mRp"s^v) /==c|mF:RLgꪟ{huc{֗^UYz8 oި')fȁ];3N[s䷂!s$ޟ}H/yv2ܘwh/_z'-v?4˩{  ,m9r^RwfE^X6D䎈xn&AZLZfN0=a5bQQ`%#eПīJfj}` L/-#,ѿEhg햝J7:ygY=G~;4r8Yd~ʥ^sboe /^ԥv[ oZrM &S=.VM-OA^u_~ާ膹_~>L뇅4x$|y]m],ރ3U|^L퓌x,gm[Snci ?v;*+xDu,G]<6`ӭҾe|5u;9 c=Rat Ae8qsѧfT +\eupkO 4oޡgɌsEʭm|5&틟nQt~&{:NU;gʮ {m|dW*7t5q}(,ɉ +pLwz%HDJOO⒯ V`;O>?yL[ _n8H^1jg9Zj}dv2cuAf~]lU@Yl{ģ^~gQӾdJSߘv0Nncb`ŹMC +7&X푓_Oja{׭puɛ39e?(‚w[^+w&Zz/Cߕ+UEEV>)H{&v 4Ħ_H9>q;fZNN{͏^_w*xP{mv;Gc<TYM3]_Uqs֐bWޔ|6,rmP;*b~uٿص'EZ7wgʲ^WM}jm0lG;#y]M/TdQaDY)m_&VD/y*jx-s=w32yrZx/{7W9UFכC }gR*Bvjձ3zjj]PwN 8նTPh֓˷]:V.D/{Ľw=[4|ӷrN/vJG=wvs?yD>|EKO hNiYEpXx5(?؉{LZx%oT~ݞg=bpQ\z쪳SܹE{ER]^شg}ϑwIU^n9oYp3}\;tnk WV;]vݙok2}).`Ic?5^ֵ-8сKILxՊ"NP|q?3_Nz5buDxN|y柌ʊ\cUS{߽.i cS*Ea3u+$MX,8(Sj6|'`FSD3%mX8Ry:1K;qswr E߿(i-#&&ou;B'/pS Fgϩ{;Y9Mk~Qͫ_&6]p`VɠS2i{n%Ε̐yM#a=VuskM&>/wKOw zSh*/y_S<#%ỻ=9|K9Kڋ$Ѹ?>* Y땷[u_|Y_7ŋ+"ZH׸,~+N:An w-_溲2b)F'=C3+3kڲs.bR-W,}/u-Q{x +ÿUc W sEd~s>9Ngdx$vPPe-Ys׺tG~e*lRtEzѕe As&}[˻م1Ù+_5r+GI,g:?ۇԗ'U~{/Ž07L|^EQ{{7xuJordCVö9xzmۄN +m$qo  ͓J\>}ՐwVoz~4~յǸf yVRx'݃Tr4N;cK'{$?+zůk>Hgn93{^7Îq֝(얏\-+/ 8M0Tlrzbǹ67^Z].$N+ZTH TԦSo:3Ao1Jf:]Wn^{E9jֱ&T]o îsÇu/0pdm}XP![oѯ.]ܗY9[Ӆ*/X,?r<٤ES8~m O608QK4mvӝSrly6/^5➗pƑЛˏ+:X]H9ZiOD.xZwӫvXZ %-x3ЄoӽOe:ol+OUǕ}ƕ/2G$Cޥs$lTܝ|9~{[‹ծ |v̍Ϗ +y钟l`a庌eqWiE5ޞM<_O&M+#ڡϰ4aKB%{E:ws9?vNmg\iWkodrMHϳ7_ii-Ol}.7q J;L;2J#MMQV޵2W*͋g6uzI{fu'ǂk~=Q |a}^{ɭ1k՛r]-R0vo'n푁\MlKݵlyv>#ݏ'\v6Xhɪ|qKO,MGW_^&aroe޺im~ޏJX)TsuҴ}wY==r̨3%Ah/[Y +ܑb}jAK:߂?yjvjVlY#4氯J4\-rZe9f5WI+ +wj$7Uc~9ys\yvfm9$1kԹMUOм̗j_ϸtzG7'x> XſVs]~eK<ϑ_%`ě{Y8j=nkc~z>W0^b҉lvjf=>淧 +᧾u1SY+&}د˧bܤChf̺v3QS9|$9,a,K +<OkD׸vܛrHԂK~d]jiJS=suY;]`=!.l*gs&Vp ~3YR=Ez^,~=s[3*T~K\SWvsW}qtJ0wM|k_2NQ(|xgf˼@\7NL]7{ +q9I_@aHz1s ݼezސo>6'pEp)}VNߴFIMsL&\aa] E"V~H^zvpʏC&R^|iߞ*6|e5fQ)s~36wbSSDlxrU>+e׮U֒1I_mYk/>/#69sUju7N3!pBv{{Aˣn+|Ѻxю}f\_iƠqW⏋7霬ܴ\zGw8[.hU!ldgu +2kVf}]Q:=}9ܺB%VgҮ Ǎ"{k>iuhuz=BmT -=gWv;u_rZEz6lLs %lܱC7|OjUk@?Yƥ/MΞ/&8UQMkOp6ٰ[qhS0n{V6!MNxT`m"n4Duf6-ߴUc ',c-v2=Ȯ$;s#1tfoH`YUͦ x[͗ NF讐7I ]MpǙdg'{o*;p$mczMWN\EoO_>4W8Y(̰ZҗL&yno\L"%"윴srnǪkM`?v1cG1o,*mea_~uCe?O,[vpWw]Ի%yӾ5=?Y?icБkf]iyi1 +wIUXWoYҳf~ss6(/Isi_ +u+/|i]XmuZĿ [_.=AzKWӷtjhZ +zS<CoysWJ~Z_9O{غϿv|OlJ6QF^䑥n_Nc$#urVӄ05#d$7~-vPǝ.$֞}*ˍl*97~M|u[s{{on'ZӞQ2SI`_ݽݙ`?0x35Jnoļ Il*vZyb9b]NOJ +W1. `6-vϼ9a_#}Jєڪj잷q!~9 ENJm}}Cȩ77MglGr¿=׹~ ̭)ՔM>d OM :^0%omn?u? +r5XTW? wJzjU]3Zܘ~o8 +C77I:1n/mg3su Od_a$3kR:ބpu9U>Z֧ʸvש%fKxuǍ3ݮq~*<+yΔkʈ[,n?i܆tr+t${5-UM7N_.!@Y_J:ghSM˦"e!L\ԬzUVm!6IH lyvҷ)T&.M϶';/ xA?o_,VG'րMKZY>{e˼5wLo~~;NTԞcGgny=|U32,`.txRsZlz;vy`Dg~^La.{+Zeqw2=Fld{eWqG<]y~8  NpF- l;yp)KdMS^dź>Y^=wG;s]}D8[ǽo^? 1[}=.;C~~&3su ꈘ M +oШZQYG +O2]raW*ց )<?$vªtM& +X:EAgJ]Sq%`~#{wݍ(yDZ\)utdgu.6yէ_:,v\/,O뿷$Ɨ=aOaHO\5ӹ;Dm:zΓK6G~Z#uO(͕Y۽7| R+4uމ-vuTEzW=PW*nb|{G5Y$v?ܞ<*oeLi|[Y|*\~}xQf;5β e!nG?|X8,zo3~C''J}^3?;QaStN%>|vi:%^ +=bTa $Ϝ~B}$M齵fu?BҗY}bܫy-5 u[=Xh(uĆ Y;r%j??dȾ3}/Y๚97W3ڠ;dܷn%|)%۫Bsx%V<2o6+S~9uΉӯ|X/꩜qլ%)6}1O[Nߟϥo/_o3qfྒ)߾YE3zGEsSr7)*˭D.Lb;3mlv3 5/$õW|,ٍfyl38bC W2\'*3Nqttnr|WTXrAEw㪈 +'I6fRfX{C>ߟ4w7]~quwݗ!_Nr[ /SeW u)U65Re7=2~} Bd//\G^؝B&ٱBqë{v>Ⱥ#Ll8§sQ(X6*H8{L}{Sav W`[ҫ郐t(sȝkRKU+{k?`rFTOgé+_ߗ+{K +?};ׅc^v=vKyΕVgTxM}8ʥ[SdX_xߤvՄ3~0Kf93W]=۽?nI?vSL]6Ws'3f֫[M>wWa?O1bi i6I'^>s3*?3oesKmc`_}fE ع$ˎDOtWvګ;y l;gWƮκ?_b{^H (Zʡop"waeƗw$WxZ%bs;̑9&&RVl{v\Ԣb6O|a4˻~s]p[ H:;þ3$hߛ0/aG>9Y|B߮# }*lm_ܷ}Oso\y֘luqi0\4캺JElk|)qwDfZAat|k0Wugǥ^Me}aS32w}xח^wJ- \A~Ɜ>,|Vsأ3#|9)3ł$t|Msvz=8 ? 4غ^M;px"5 M9_O~~/+yx6nOHqOғM +lz__ߣC\ soUO宦K :&3ɵ-(͖xnҤQȰeINrdzS\F@]|{׾/ucAnlm[)]*yur*29:~*YbapebrD_sV&(uQzYur ϸc՞a/k]U-'޻`Aɳw5s0YuEbЇT}wHvy-Wt:ƺ{ʼmYlͪ쎀k;>_|j\bŔ 5x::rX,~M7U|]c;I\+/Z=n޳s>)rKm+/ޙA|e}{l)/L[y!לwnY͗ʘQOB]muc/'9ah^]ӡ|zr5~{57bȹt{=~w?*̞r^ѳ&rhېmGu>̱EW2_p+Oo<)Fy S8c›tӃ//pzGzw.U0j\3Sgr/ҫu+xkl~n2k]/3gٹ<=v/ +}Q W&zה$vK.,c]ϏhsVؽZzEXF@Broý39_*,D#Vo?e䍵|IA۟D~z(o9+ļ$w^wk& k/əV~=yPOp=7ܲ| +s&~Ux]6>W ®fۿ'[[skŸmxm;c-[DvQvTĎǿ#4L8aVIq :8-16vwpM{=1tJ|_ek{1j6xn$F3 Wt[NHҾJY엫!^Bu,C>G_zs+ 7V+Nxc /$Z9Z-P}gjVf]ǫ7tkRֻʷe7w6[snkPmt1k:o;y&X~Y;ZV;r\]R|줵/o.)(3mܓ3s Z*d?iEYynK<M/ ^=4>}"G%pYWS®~}r\yS&HOiڢ=tc]+^ޘ&c=ÿN/z3*VFkm9='o)?ȷ-3ғ{oW?aM8czYfn>Sa)iwgۺ;s$*9vd|SL2Ig]ĻRfzLd(Lu(VpXC5m47M>/!׌ m9E=p)^q;Bn=>/ŽswXXvmWϦʳ'KM cġ^qUELMĚVctA&-S?"?*%`iǭ^;_+Z[7,b<->´#O}z/2j˅7,uyGE_Zu,W-sXJUBGKcE47'>uXHWr)U#Əֱk_[aI_>\P_a*= r>te +7G g͗߰{5^K{BD-Ss=Rr}Kg_pvyqen~]f.M8X:ե\{lY^v|ܿߊKYv6k1ӧ}魈EV)3r~v 5ZʹibգՉ. wm~?9f{ g{N~P}ŲGIО+xɭpNoM4pǕyrҌ E}{Z{?D'_Mx|5i}Sr?M3xio'\/]x[JǶziY`Y쳯/~6m_#ߟ{\%߰4{YĊh8MrSù|>wG^d+7سT{ubIb>ǭ˞"trY 뢦_%|o |oeЯLcjakٵWfڦpZu)I~TڴuV&hWI;1obg wza׭vӬj+^F(: ͆E{P Zdzz僂ww +N9?YOWZV:,:],{cF*Y] cR_oxI̬IvU??\3^GL{8tp'mu%-jO&p~KAt{QG߹f# g̢/: Js_a5'*{+з{w ŵ[`^X+w崾ܥ)S>ޚP}̘UG=_'#X'ڣi=jWz cS9#%vMf31e24.Ϛ[x9f{/mb˟~L޹ry&T%(\L+R6_BbsF23m6[K`|lg#@S o\}U9[dO|azDjuN[YRۿo~SҞ]{rN ='OˢGʱJ4Nvv}u;+uBoTݭCѸ\k:Hn>|SOoz K>}betSZ'd Br[os[񄹟X~v{ةGVyu/VϾ[Ӣ_n{vQ;3z5dTsZIpR{'\Vm-da|}9;bZz*boxEvy[}ڞ38TE0TZ^ϗS:pcBwynW+5n4Զ,U%{/.udy+_fk0D"E"Sslw2w)ۍ,ߞ`N׏0_zDw _,}Ǜ-Wo71crw?,/vz;[wqbunWwlU2aRNҼ}M!扳n,ZlSݫ^3*WF'Nԙ]Dab=|Ӥ{l2#.n{Sީ'HcO6gkW}J eϭw|*]1V]u#29k6gY8w˻Uf_e)c=&5u7dvd?K~r]zw}e풊b )=ȷ~1nI-Kg:yЭ叓[8lҩjstób,>=yAd[ymNΉ򕯏wMwn "bS WLߦڱP-R~et5 #m+L}o\gOKh\6m{{ݳVw֍A &T-bol6ްnVG"#ێ~;7[h<_/b.u{O}Y!aBkgz9ƿ:"$_RSf8l2lS} 9${}U+w~].̒q!zTy[OXh,hmzY3yrU3zL{,CE-f?r2ɺiU˽3Ͻ?G_?yczWVڼ&O}9^fM7gF&}h[ kXi+mfE|py^_fal]Exͦv,hv)Ng.]M.t;tñ}<]s&Gݟ5FWgicI[$ܶ_ܰtY Gf(q/ opu:EgQf;Sn xD 5N3^O#qS;=0\/usӓ +9te&/<.8S`-1\l>n;?7lI7\:ݫ5_ͰXs}=I9o9XڝWdWZRu OC~^=Sw*|Ⳓ_emfx/GOOBeq5X/>8q铕̕$q{BiLJ2I(ery0.MNJY2&n3[nWGa9͟^])jd?]#Srӊ{7œOeo? [qKPgg`sv{SR;{-N/=gNуq3%VR3/x뷢 +ܼ*?Muz4=BPpơU<_}3|:yQd2{Y{K~X2:tcʔ޳ץ']RC2MFѯ}D9w(Ig& fꚷ;VK,qU;'wf=stΪsDL@kƽg:u(3Y¼q|v5k7?3WYZr.ߗϲ wZK[`~v)՟XeûCS'`?!kCҳVڛwz.x~5D M?'#5N׾߲o0޽n8қ[J:&s\61~3MaܪyO\91nkOW^ˍmYM%8rehh |xW934DxC{7 UG&ɾv^r)TQwAqr{NDLqO(Rہ/|pu獵J嵂kdh/4JٽvFח(rt> d] Zʆy:h6e1<zdǾܗWO(]5Yj5j]kKcTVoQb׳K.;d*}'bۺ?0 ݺߚ'Ml`ﳿzCLn}Wݿ37+ +CLpQddEy Xm +n<ʙbV}Y D糾-ۭS~4B{JEa;~sv[M2?𛥓00{-{ +Ϣb:ƥI+M\9(5wݡw qϚns;-N/1,q9%T54_{(K_Ĺs\9,̥v'9bX fsvmY_|AW/^)ׯ2с6oEaHY]u??{!ڽs'{Q;3/1*uK=tV08|V<_<ϗUd:9_jm>2Q9m͞.L: L[w/31f~sij:̊E1?0tFp^vͬ /gXuJ높VwuV0<ٯ5-`w<^X^*_3; 8qWEE39*oڶk|ϧN]7m9۳͓t'}HSW8繱e\rxƌ+^[0p^t^}Q /r{=[sѣ,_6#Ķ{r?0<+WfߤU"vpu9ں9ʿ:0]N^&oc^b0NA!Gv ׾n=uN[O1()[,}% ~?f['Kfsp(˼O +%t1zA-o+[3Ŗ3)NΑc;P|=%l>& =hgЫQrٜYDNO#\U,Oݾ+z7MRd[\v1˜&{7G엦f&mjXjoO m[#zɹכf;ZVUL_-)LzQ{=+q.:)yL9-`ظ{گRolt˘Kvv5Ya)y)kMe,\bI^K߾;m`Ytb›ڷ֩^~tGgE $n|,o1{ơ|3]eDgud|:q~ J; kf{J3KBvԚ? GUgX4ZuIk +}:RBzZZ8+nRP e邌u;z%\p&$Z#3 + V'/( n)Mn^fW{x +wywnDJcaIOYUn,$wWi75]CK2p UÚnyJ}/Z5޴_e Ys쩥o}z\/vAV0NZ&۷|afҥ#[,(&'CjE˟?.lw'gN?0{䔷O5k77((f7AhRq =>]ʧq]^6o)ara0e/`j[3ҏL)>KRGfn"ަnP=vڊem]ْ}1D5ghjwrY;^kyY +76|\2K5ROD,~nrΤ{7j¼ckr/67gfh߆3KE2o,bOv95%oPX0 _.|%)3Klgjq,:Ixoݹ~Xbϊvh:&0Цq]"Ko؅5~]&ޛaYeYfk/_gFFY!vs D{$ucebHNUR~Kʲv=ES{*?(fܹjŝ]ꩮϔr8 +_[-ǽƟ'[a2^Vn:$ApjO;lox(mg.\//:okM7*v5̟(#m2[[ͮU JLns32Mk9Qg~λj_'- +3HTm xG~go<sM c_̫npŶIw$O]W/,_F6yCٹji}]ڛmxض|:p$_*{*bSx]7?Nz!˞Ӥ,{.%Ytk=1-AvpCsiο/S{iqwʅ\E VE4nxp߇nr湂nɶ˝ԙRKn +WRIi3SFvȾ8*y_9N]f蚟}cES˅l׷#]Oޥ%mr0뛵/}֘wNPS>$ Wuhc6~vg/DuYL:{M +8hH>aD>O-t9S}gx$|]EueTGE*t&WLn]n] ~SI]~ɗ_"(BǔܽҍR,̜l_2o\r[fWMbEOc'&NTvVm,~ +NnoY{_v'm㺛Mcu3V1eԻk~Eճ;BW.^ws^}QݿbS&yZD]\+W(Yibw1w3DtjbhgB%>W^줟)0MpQf 78ES xԍ=3?'r ˛' +EMsqo\^H>!/&;U荾͜^O?o%΃.eCgn8W)q󁰧5VtpU %uBgV7+XO6f":[2W3fKUXpS$s%7c8SťxEo 샯41SȬR'?ebfώ7wZnWwW(s")Z7gU+,y~̌-[Ď-oϾ?ID-cM'zB{kt 6zx1jKǂ{AN:.jmt`ڣ7>z.eb.2ǨTN-?}'SoI<>7{r߷GmN}sZ1b@^'N=yL*6-gg<ȼOgβηրIA25I{TTUqGB6+Me>~Si6# mϾ3n޳O&i!jcw$;m.WynE(ayٻ~rf mYReܐv{sۙ?~ؾס +g/508knX6~KV[`ƃ +B,FroqiWZ +N\C۽4e]Qu}v~{^y}*^r5s?32e_jOe +S֟^|,!EXC*R~nu2GM glO/sBU*Xb|SfQYW<_r&ϯ_+9$ӥnD[ ӝK}Y.K]tTɻ&_X *rne^ɚsqU+NQ8pN;*l;]:rAh wu'?Nt=wCƗ/a _-sZݏZnw^Թf55}/|NM;?uUM5 +.=wY m<&mu7Y/棢Ccҷ(ܠckk^~乧{"1N_VK* .yy'$%YdyߥNc}637Jه_THTX-Y+]5dzp^YCλLjԾo +ɫgnuU:*hewx;#Fbϻdޞ0["FdF޻\|;ؚzʊ5_v&'̦exwʫV>J\;=m+6yJTLYsse_,[R][<{* :o_rY{ [xf4y'#Ţ@н]gm.iLJ:Vσ[:IrޱfѻK,XǼkJt +Xo89gM}f}6爼f(k᧢ʯ/~y0h̫*R~ћwyǂSEg4}v^2%]˖\Tߣhermgu\)j0k]fys{EmNo8Բ3/u|+`Aˏb^+w ) >V;CQ-'gxqӷJWnwiʥ۷/Ih%Qb,+9GD/ksU?̟ܩ4.zˌԫN4z]{h7r?͓\صG)v m+..6?\yKEI~-{֜\(;O2PZŰ#̷o卶C´w|{w7;Lw'/7DZ^[?1>v-gѵ6\wjԘ|t{C& ZD蹝5ki6C~\^;Ѱfg&/D&v>{뻧Rfu[yh8J DIv}amv&锨\5]$q_ǫr?<*y_,fFLܸ߬}pUD@NV. $/~̼uԎ>LX3Tv{˕Kn;;_ߟ}^U:aپg%J]|`D܅O _IMijSӎog>q{\LMc7_8>dCBMٷR̂_ wIߢWu?^S7E!7z=FnݧѴdќ#_ZM |_lɨ?ϥ]ד{6eͩoά+`Tk]~2\@TY nVZm\$_[hr+*͵72`ZQY!'ycNTysjm[ ĝMno=k=.(L۷ޏ?-#Umw@wX/g|z7{?,I|f?lr|kf羿lt$}'ۙu o-W`8{"BbN׾Gןk<^%?r׼k<[ݾL-Msy`OÂΣ {>qw{G+G@pۃxM\v6`C+2ns<:mwL6MS˔<}}d[z_b-zgUĝ5濤hdG3g6Kب&]bYEZ+zݿժ0{_aDeᮠϾwd;cQzXbWpnu!_-{jIu: `}oNKꋟgN'_]s;)wv&[}1R-ykw?z,Y%g;f_|kb~znganЗk1o.j4K+˭C0Q]卭륚E0gi gX4^*0}Qׂ7xhRR:!~XU,"qjIyuM_bI_~tT)wy*nokypFؤm4(q="rMߪӫjv=t>j39rMwm?j.[Ts7OpVe_-\x[N$|4Y=t_׉>PK>}j"KVw8rxBcNN+lĴG˳ΟȾy"hR7;t 6qa^ 8|1ף{k7\5 Z=EV.놟G<]*gʄ}kz~= uXTwA JWkj0\߰<^kVgŋ(ڛݓ۹,~?m`ΪhnGsˎh|MMpmjϵ/K}ј\B[?*Dl:96C-p['40~\zlwʜp[%w=>[xD+pAWvjH>:gujL݃7-j2|="冟fK[g*oQP΂Ɠe~xsڶc%侹U_㼵W\=HwOl߷=CŷOy~rULO]9T%SO%[+}xdfysUc^%/|NgXsʲzαSN߰⍥Q]mߘ%[׷:"ॠi~[KWV<ޕi4m +6J~rzgj>'dsyU<.R$wE@05˥Q /L t~18}dMƒRF,;c޸Qaof!7)[:Ss&˧-̗ػџ{.ɵ!hlI;Ջ5wo%hzR~g|=-T.Jtz!=/Ufot<^+ƴIQ4ٲm)V9()^;y+?Ygާb)=@̦eI'V[MTjۭBz\ܯ83'&I…+xuWOjK/ߪV8"ps +d~ӧkȲQ{M~^t>!{,̛'^ofcϴuc+%^Ujz繿Jӫ&kw:ԥ:Wb9_.˪MpUh{3S-9Ch"=.nz&l]$0WTXAr#6ֈ?$P]{ 8Om}WX[)e¦'Wi<; ?7v[](}~T"& ol'Mm>[wGy ӛ+Tϛg;rݪ]U~Q]T帴oZ8e"5Ҕ]f%]\vdDrhix˿.MӺziR(ۍyD2M\&> uAE 'hm><^}Œ WKƶYpkՒ/0^M:ת; L\Rxf4A+l=ӝLܭ)lUW*w.zmWA˕:Mft㇗O{O] WSe.aÈe}|oĵ9w-6x#%KU˲/96#4z=k5޶J<}xpik_g)7jH:s.>3(9=e޷m_?調+jՒr;<9(piESi7K/, +-/TRwD1=aV;S6kxv2;H")I-i˳뷊L# ]OH}wp)%G rp`9^ǖi9*xv9?xؔW}2\lrᑻӖL|G[[OEijH'쒚sfHf͟PS܊ +NNUb<+gL/|9n\%񔠶.I&S,gחf[?7Q<&L#6^pbâU^u2ɚa GO}P|뻄ޡ +#>ieY J6xq%7\[rMal=wc:ێ*\lr@'jJ7[sh&9h֑G~FE_('Y)kk۲dV*{<\PeVzE;(fdtC1}v{,O}\IWrUsZx9TOo eV6mXPՇg1XJΚw5YV%,̟nwtn=y3jx.%O9WΔ^2Q?,>wb=oKT,T'DFq-Dy%5=k:/H~y}SVD|[;|w./eZTMjFLd뮤V/Uu65-6kw]0i߫9q9Vw&]}U4.^7\3ZuT/*v+W +Ng-=/4yVQ݊?֞p;1p5e~7.|w:wIynk5ԶaoᒪxzWp^~aNσUnNnh: m:6 ^9zᾅ2+ԥB ?\Ҫ;\w`\oʧؿεy?a]R}I;ǢpO9zU[eSi%/&}TowbyU!ߚ)ZǏ/pp19Kng~|994F] ?CFXTT{3ed~QL({b߾4lTh98sAʫIwX2O5 {g6 YR(W)8Bmrwr>_|vՌvuݕ-'e2pUW0)XBgOE=yl-WDQٿ~ˋs^v68~̟,wIW8gW *>mmViXsQE[3e%sG +|Ӫss7qG,BYc\wɅق4.*.qLCrU|~|r~Zyn~;?ٮ|fIX uEv7%ٖYW %wY16NUkv'.l==Ӷ;ˤZ7;-ϙM/rsbm'D_e +Z_Y[vgeƩGw[tL݌[}ǿBqጹ/t1a«znݾk}K]/FJ)t|UhbDrF۝c6m.&\!8ߨXd%mP֬8+b;W4/+\3!m>olgmټ+_o^[Vu"O]j(eǯ9%2xn_y-%gWRe?z'&9\xoa-ؓ[(|UV§aQo8  NwEkC҄we[u3<'? ]ߢV'u{PH[/Հ뻯Ƿ8|) ߭_[L~Y1Q2Fɷ# =2zƈyEߛ]s8uJ\  zBÞ~pA_o0b~wMƈJκfv6pލg> G,Л*$&hiKXu o﹢k5ۼOg6p-d]xe2eD/JXfZ/w0wNǷ_U= +~|n 7W#׊ߌq1/?*4=:>/=}o_sו.j Z3OLzWH'Kf]cxe}p}:Ks/&Kxq͚~޴:яrbdzщs6;M1s>}A2u۬3V9RFss~,ø-^~,_ E8n@Eϳ^#;%SFޟw?cݢ"v#30 R{ nzb_좬x%Μ Z]zM IWfz5\ {ٓ^nݘTꏥg'4ʩZbS˿gJީpVd<.=~0 mSYt.}QVn-PY]|9#;wj /XW|Fr_ƗRWy+2c_;Y{LƗhneg52V;_{^{*^e4&nwϹg5_IdVǵ&v<Χg{m}|7+$bpl֋{q'سWLvhw3U6{Q5wuAWw.p;A5[9EZN{ܸpV}F.ik;+,̝h2SΜ͏}M<],ᔾ)&|o yL*8~cZ[ES*Ԇ[ûmýkǽxGFI=LԷ|ZOIv5m-XDL/~^'}]i;?L]WNJi:g^:y:LX};ybazxZ;ur.iw$'m3E +gΈ wu"<]VaF l Os[S$,Կ/uyhLrl{ҙi^ehإۗ6, ;X)t]£y>Ew5>wyPv_~haڒ. 2歱4 O?p]ƽ1~;bsY =p]7gjٝSZ&[C/#t8v/ȋteJ~溤iNhxptQkX}g#jE|Nח}U +ST~MRapi)>5nv*m]Qy?U)8o\_|fk>_ZѫOtC +WӦl oxlŒ-wWp2>tbFՈe̖=$7+);מI5:d~׋8L:#Z2Ozy1Y[iZ]wO1;޻`}w2B:Ů;Otnj,{1C +񁒗Otx"I=K⦚l7:\84>FhZ/%R>sy8$6jWll]1w^>kJYFjGڰ]u#i7^qju6C{,8kuBj6S65R+<!1ٱ) oslc&7?ʫ1X?&s9I[P_,ncJl_]VW9a{3>_ K6nñK4^֊`:Sdkdom1vߜݷe._9W33.|?[Z71nf~vaLŢ_|'ML\eŚ>8GI{̏_Jſ8wCB_kWW=Oq2pS&lx;ڽv|=iԯoլZ}ѼK~n-7*pԗF ]TtR'Qg)m>s.-GK\`ЕXQU_Gs-3?tgC[60jms͞s?{KYUgXEu2Z=8Aw+S%%rɯImp,<1} K<3k3+8RmUw{ͦK8b0gnFR1{'rETHKOle1{}3}+\;vXxOcl ~qg{o0V御G8-^>ycyYSٖxËygjٲƬ\oE;&UM$ۥ7=7N~%Ÿ-}mwNhl敿rWy^U_TMsHS=Ǘӳ=;ϓ>Q$˜C|w7x_? 6G.KίWrHWxϒxJz8v8pͺato/&S4.-tm%Y˻TLh",asߥuGd5)nOi;yJ*!㥡l+>oXWpBÅt/^IOv~CgMdhqBRl/#q[ni6 <'~im]~ul*BGg_OLSz=݄ƕq}GLCᆆ5zi͖=a͇KkYgW_r0~S^uqv==^K)Rh=/x:F%j|tYP|BN_+k/u'd:WEk9µ08]dG>X}6'Ohx1nLGZx׬l"{CuyOh|SQmӣurTVsdUe7@Y5B5xi}k6}[i\X49 ܟe.zbΤ{ֿXy%GIUBY*Ĉm!K̜E~8\||zq-J̭`[ἳZ_^hx8Dwf/~t5'|4Y?ҲsP}av y70z/CbstarhM,RWYdCxلNh<3fOigi/)do]3ʹYA933\>xm´YGO 1lAU}?e׵I %~g m{^DA߳."A~Z \) +#&,:o~g<ÒnWbf[QIowZzfBՒ"r\6ѭ)+c7i*qkou ʋ&Pђ_y$kՑfnKkzZyw/:*G|XoKDkm :QtL_Y}MLdlN3a<5O> Ns4v/['81SQ$mWf3gwq?o1PF;+Nun۬c}"?ٖ~ +4xBBvOOn4{Y_.u\RAz;٥MBY֐{w-HK 8à W[fl2H#KT/y'ES\'`J} U6wEN.qWm_QvG|C:G,qV3gIH00Yc΍v?\3꼗VOS.q:kǼ+Œnf|@&sWZ◖ZRo0;h{â׬s_(ny)>Y ?u5V?57]'3(w}C~MͺsJ"wS%,yf?q\۝W`qy7;߹Xڲ$oxw'qa3T=YQM'/n1q~l}K +O;7TXf`)'5h)V٨{u}Ͻ1Ik"wsbX/͵O=xpm8vZK({J6=!Yߤnsc` o",ۄW 0T[vL%fy̢>-z2j%5/-INCxgZo+Nel 7rt7v=\Ss~농; +wL^6WZ^7zelyZ؎-kz]̮oQsT~Bc_dt|!G$-7j#ƷEZkeT}˸ksRɖѓ*g_{g3.W~ѱmVug0?+(2r{Co'>|WUU_M{$kg1(_ef,qLvM?»pvR-4SKkfk~ӦCSWoڿd*YmwW/~λDZS_??^_1Cx_tacK^ +bh:#7 _]]Vo?I+6xnZp활q>[7>&fxQb &b_0զvopYA_duZ Q/ʗ,2gs\w-?,tSEn;؞D=>/diz߯wv)KZxFaZ5iUNDT'9/W}=[#7p/:VׇGc֪K>ff\QnЭTQ;W:L + 3COu3oZxkSz>6]1d{n\Ѥ-' +rk'>ƨ%]2=G#oղїJ-peu'~slcs4NTqw %RwYQ}wOvu?jyqLdeE3NK73JO05|׿/vr?R]W +:tUvb"&Ա}xXǺ/ӎ +zk+W+[ڧ-]?Oj= +tӭ:WZ:u+.3YXozz.LwEh +^K_W="ʓqNJ5K-~_&t)}6"B^u]rJE*F䷜±fKO3B7RILm\@nۧ/9f{o}]~/f W1H`9=W1,h+M|qbLsW~m/ʓ +J]͖jo/siq 7ǝ7~̶+޿sۯHPzo[V=1k纈6EYOqrݖ4wS#L~mց坓>KVz]ӭC?.Q|jMQz//th䨺ϫm/ܿBy.&pEiL<]W|z-'wB?TꭽG9/9*ta kSMc4m y&&b!iדq6΍5ZoE,aOXjOW8td~n\ӷ8yܾZi!B9̭?d֑>AjJw0Epg:s=?4/ū79uOIR1[ZêC^z+^/3 Wk^vǧ>s>e&vh[\wyYη6͛zR0xb믏gUlҖ\rUf's|kϘT{G̼8f%"9[s~Nurzӹ5=O -̢'mW)DLʛx|JnXɞc`mza ׃-B|%+~ؼ1w?ǔ)Ǿv0SRrY띬kQ5箮Z؟TQխoՋ^aiy>\bU*?, +o_^<˯,кkq6Bۯ\V/yS#WlacMm.~t ˥uR{<*.3jD(ht}z³o8+h6N6{f|_rgn'?<_UE"p_Ndo&}raͯh8-J`%;.;Q/zV؜{3/z~n{ȹC?gxu\ޭjUp;ԐZ0{'B8=0{%\ZMt6mv?bsx2{]&}Vqdp\PjvK?^ti^»5~0r)%Qj ߧF>^h ˢ+<̒3E oGWzP='No(ӑR`7߮ĭs6/(-V=sCD̸þYF,*3w-;đ[{ϕuvYr-!`sMuދu}Cgo^7G1v)ٓ:wj~yXWԊC3\iOݔ׹?sYK$0,#;d[Vc$ŕg=a[?ʗ rre +cS*;]tdKl +f{ C"$̕NNo`Ͼj8eխΩ=o<n;esj+*TCrW;WB׳pFܲ-u^hcS+)[41!&FX7 I˟Xzz=&/)u׬ɕm₃'bݙU㎔P3! )*swfC=O+s֛kz}6BK n؝6eUS|̖I:)ˊN=s믏fT*ڭK{B?>֜W}\ a'h3&}\ZQ8K͂ }?.xWPv?Tx5s& ]t-NayTҵ$)hW=2ʈ5.!>); V[}j ,2[vM{u[ʻ|U/b[[.ig2ݷXTD#s (jN;Sr:Xw~1v^e[KW%wj/kaG^[pc!3gMe^䏓 {HNk ^!ٴĿk;{2O}fY12r-,qf]Pp7k?/`Jj]|'m8D>LF2t.p28#-Vs}jz|l [mta_Z'*)OrbF׍jyN~+L༬'C +zf5d=AwF\))˂v6}*3Y.-y,V~ ^I[Ob֝{n}SU >r}7K㶮fӹn?3oKLՓ\s*{Bv&.VjfW/ޓ:+Y5kw䛶~bۿϺߺ]Snw_mg?=Umwә0[c Wy srW߿/[o]^v6*8mi7O +Lrw7i.ք]GLbƼvd$\i3W]Ojۿ<1BGk騫޲OM!=iq 935z+tls6)>u +p^g헯|k_yqդ_7z f&UvHOqĦ&]_y~N\o·&px~zQ2QSoqЬ\J/fدr~uUGٮ9MYq͙po$ {ew$f곺Krv-z>ٯ4w})swӦyg^ +ۿC`i{Q(7!uO +=f5gmASSt/<1NǛ]RG]F9R5~xxU .9%S3;7kkLo$[S=[#erF^s n9sEi}c+뜌5EoTۦcYŷs'2+mڷIwQח ]jw\m]gz?$'Qtiؿ''Bǣ,wmdsoW"@#Eaȕ7F/NQΙiaĴ֌]TC 9#%Zοo4JN߷;%}-ZT&:/憾D?/-zYg{.,ܣZ:/tOVq qj0yj ^}>2Sz:Oh yPwË/}>}pf7*Vz>5ˌ%GR?90xV.q ՟ΰv]L"V޻6f:zяf~y$p4їuiT>3EZ+*Z(K>^"UQ`WcƥmW뼣wyhUKIx、/yU;try&|u.k5\_U| ;vv<1;(ɇO#B惿'@ۢ M|#vqJ57*!!^gp)|T,?-fʮvfU7K&jٙCGʔ.oO}AmϪɕ*g?ZvmR_P¡Vlʞw`GIUuy~W rտU8}_ܯ1MF!uޱ}T3lƵWUk)vo<`Z3&/?,aދ.5K X5~>m-{éW/XCsV.0'ŸpMm71]$Wm\{FZNZPUpĵo>w D1j[F\",uksۛ7k&[ /sr(ܙ fKq_x-‚ {ve/ޞ&Աj4+ A_1[o 31 _mf~/fjjʼ6#yc:<蟲)B\˫K:;e%wtgU'MQ˛s̜sUMk򟶷%xDf?8e`ĴӭJ62;8kY|M/r;xiNx8uz/;ilɞbgc։ OU*P{fwM!3ҕ>?z|bs& ^r lgY[|q>?Ss孏Dua''})ZrkCTܳ^%i9\{i9u[A֫iLM?gg+n] c7P~%y\&!Ϫ4oKO~=\6nf_HeOo5sm`sY^a$OV>}'>ڣ;ܢr_oľܴj;'︗:GuJ۲OfrX\4]e$Q-&,(O۪p&Lʪ`saэy?d +?VMK#O8pedI1we^~?C&M$IV}ӎ(uW>x!ԃު?_ vR97 +]4qBp'TlLmn9_-N-xlÁm^/Ogl5wY87}:|jǤ+U_ᮻÝWޜVsۍWlUeTxl{''N=Ge>pZ>0cY K^a|A{ӏnw{ v*ŵ6zI"i^'[[>5Y{(u1ۖ&N+;ޞݞŻLpiW.mS2NM\eƋ+V|A!7&d{;y'(p(]u~av^smj|e>~'j,pqޯ$qo2Q ٟ;FdY$ÃcD"#W~p%aUǍERӣU$<FOfҺ]RnXzFN}x?=+ cTsn\PY4o/GT%_Ϯ+:/.'?OqPdCߝ,~=}s.7_7#rF~-;˴7..^t$^э_z}= +}CW\6u]%~=|޸~IлIߧ3ߺ+sll.Zo+Oٖ>3p&wjM鬯3eYծkWh-٭w%^IdM]2;.ۋ2cqݾ\םaǽu[sZkq '~M^M)H9[4!UlҘt_v]^nצRu^#x\VM'Vhd?p6jOo]rrdjaKeGn,ݿs?y\vLԵ׽ +x+U~1%Ӧ( ucDKbХӾ:Z ̕z)biOvJ{|s셖n+ kn9_@Ou{g%&uǛ<Ocq5'RS:s˵gvȜ˙QzbW[giz0)˩YvqMaq6m s^|!|) +pmk៶?kڄӎ{t,ߚz (_ZdʷssV"7)kIv d} S?å㎳~XҲpadپ{FxhqgOrUu<ٿ|[ KhwfV{WglN.9=-0ڻ܂E-[vD$Js˾^j[^xҼOC?;XJ2=] ̒<@yˢǯW?KnphYZXyE.]ڞȴxjG+ZMmK;g/.n)Y\n{e~ג-[E>D2)Fk?uOTm\ؿj̊2;?z471/j+D7mm[ԠǍ JN};^!My׼^2_Yti{i{QE-R~,u oJ~YbS["E;yGֿ̃o-7\*8ys$K9ae$k_~VM%) Uu?*^dezرRsn*4|vϥS9hȽ#ocp(SCVws1-&;O`i$UQP0mYwO][(38ƾ_<%_ |Nmߘv{ަ͋;ߜu]z닱L}[NKra%k?pVHq>wGyy 3~ 72|XXfj֯in_(YF7g-:X[}Xu2[[M9/SOU^a=ir` dA|xN9,xh:mful~zп3aTU/}? T:SvcQo魯 +? Zpab̥Wt)>=2oKǚF~Й%+*ѷqCI_ +M!>[ewv1w#D8hyn3߃7h{?zb,`8OKEw<18rѶ .7HîWve@śSu_tPYU;aǪc7ծi19}n&.zgӏͲQ9c"W95l׃ $+EVszzdUMz'Iڴݩ',\ɲmšL otknH)Zsߝ ݝzr.q3>y w󘖗TaYO|2Om]kQҹH$tٿL*j{po?{aQYYsɮp.6O>|oce SS*=ԙklĮ֎1)L~~-Oh]\3{_{[ۇMu7O>uޙ JUێh锦qH<1νOI\0e)s,礛+5x#͸\6Y ׻$Yڭ7[M+}uTY*_o-J?qx(˸D4o|>$/`~s^Xa-v0]̢/Xa乫"ھkMH"s&)C,V9k +ab}W96g"O,kRsH5jUg9V'z/,N%oقt|g SLއfY״|Gf^0]fo=L$ms@ΈSIw-Qnm?Ս{.^qZHJSAif oO~"GVw{9TxkF1iipmyv;ku 9E[2|%ٵ;9<Iǿמ{uŇ-BQ>O%=ieO8ejx5eۥnō%6=vVo5Xohx纇KW8>*$]hIG&'pȻ&Œ SO:n2}=WU6Jx-;a&GB7dNcWZDo ?k⁠6" ;n?>B?TmԁsU,4C폌6K:Y )B[Y*tԇ-6M;9;HeJ܌pV-Xyz <7z7pmpx lݖO ,:+x$|wQg7Y9-VH?iүu)h1߲$e뷩N.݉L3z,gz?UoB~JYmQ;wa8m7_?}0~#k.w!}m6+I xT:C֣_T nt}nrV/2&El6n_:/+%֛tADk+\y`lfM6M0=ε:M_Nv 2o˭_';Ą9W&@a۔bnNNga: +vZV~K噷lڥqCdmo/l +gį%53?ն{~(ơs%QwB]Hڢg|4YXj=_|_7$rnǣү8sTv +&ɫ]SR1IB5פͶ830+Oe|gCpZز7)8L| Zoȭ?|kH7- +Rq)3=]ݻ_n`cxL N/7<hl\8h?y|XRNW]vIn;–( +gLaמើ"K'&n{rgÔM:r~(_yTҿ@[JK duw|[]"jqۓV _G:{늩, wo_4JOA0=VoבËVZ={82qՍTy՛ .]%J@1{ª_T%rnowO]ve+&tևZk)N$6dfHw>wf M*F`4{ֳJOϺ&8=3j27sosB jn(|S37unLS.+#K]]^օd-?,;M,N<š:}B5zܞ?ꕇKnmhZ]c ̝Fv淍N\6/'߇x)t:z`-_]\>1g>d8r:1EKt[Eo2}G_IGrM\%qi]5KlCJw_>ylkC坻H{ +9M~"T|w]龽 Yr'̷ sf#E3|Ԯ+:Rou\ݯm3؞L.i?vسh7_,{ o~v לwddF q^KS +v-=cz)iQ7O4yZ/66F6qϚ5K[U؃IF)vϟTγ% +^20P¶_kl)vdeվ<ӓPGfƫl-d {`;,"_r&^ڽ3OWک oٗؾ_l^ ԟR?ώwПv!_͆ۗڞTyi`eϞ5٥ߥjDۂ/V3g%}N {pㆩٵRm;z]ܸ)aq5^ +?~p%[= u6M|wSæ*`]ūʭգm~ukOy_< 2x997مwBU_\|^]W;jҙ٦+؏ڴR;qb=)Qǵ:sV =$H@-sY~ۧ}yՃxoaVe +N9 +Ϊijm4Ƭju~]5U̷ʞ/}ڷKfI ja,#̏R z/(nܱ[&7[7/8fzao%"ﮜ1ݱO'RnNK.}>N\s<浭\Lzf2:?m3N[TLt|q`H\6>{|+dY-jr64ףC`I<ھo;.e2}tUK[ot`˧|MCzݺwNLոc7*( +Q߭$S;E/q +V?kV_bQ{(gaۼ6E%~/N!t7j!3ҧ"qI6*Ѳ]xQ8dQgWUQ5E:k,lYav"RXKnV,JQw5Bŧ5?{y8}!Woh;aɷfJ(8Dg;,Y&nç=ߺݦ W0HܤHCWhYDOKtPw[ͧ_2֞4«u O-ͮ" ˜U].jz^O>LQUCy]narT{CaNÊNx/\ջ >5^"ﱺå8ٝd"?LJ'pU/vܩ/j̘'LL[wCvx0+O1/l񮦆T.yb)w٪MZ??? vd}ubSŖj-So86X^~N1?Ÿ^;=չ'O>u#&kF7CKy9D|]vEm>iGs]bbLN}>jXxSoj+9IZg +3%fnqgE?.:5ע"mN9lտyyv%POϜ3?GMU$U19ˏg6/-?SwOk%Zt@EvwZ~:fEnQ^3O7pCXrsN)&%?bi5w&A`‘dkne^kXr`͙MXD{ߝusΎ;ӯS\߷S{ؿ's/Uu N}*ݜ8;5Ǔ+&Y0k_M;>!G}o$ao9eqlU}䠹fWٵoڪ>H\:_v+x|h=قfzj';x)7ϓ?ur'8a=Yέ:ߊ𼩦WLer=MzonF&4Tڽ4Z$sνoU*Su:E&mX͸$"&.Ƭw-ONxXWf^}ɃV.k`h,**m; "i:yK O>`*]W+7bW?Ĝ!z9orqeZkqͲ@UclSڒ6w= F3g1.5ѲM6jϹB޹VxYە0r0$tWTx3/‹痩>/)ܞ!@~1SF'M.).]{vW1o' M}`߰Ed5tqg#d + v/ת->;ϸ_o}\Vcco'mڼL,{gҍl++˪xkZ͟u_!7lӞ<.goɬwN۾SkXloֶѫiMҟRK.}4 Kx7}ASnt X'>H7{DUcEB +cFÜE4Ue &i>P g Kk*3ﳾqiBVϏ +?aR%+9<.Gê}Ƿ(+eOqӏ\~`I9Y^Lѓku^)L1s7͊V,ݹSc͍˼B&f +sǷ8/Јjnao<ؒfMw6k%~2=P-?+xVF[=9Yھ|qPA3>䘱`_.> 9s-odKS?'&FX>~[ w^?[FFEcrO:6O5.y~Cbs'o[nJNڥ&|* 5=b/4|CR|h"q_.J<^r.6jy?+Zz "K]%m")^RM5i]ػ=YSl98XVMhRY&]O9,3;-fQپ/:i7^a%b|pX\~تpk-OE<3TnOkpx^OFkksFmoM=WB$}J1{[ +֌2SY=;NZs+rt|X}z 2Yv>ZP3XiaY?=w?lJl˶J{؊-3lM9Y9 6 +T\[ wޤq:(w+t6["TD_-x0_튩^G坶%+)=|$dnXե}n*ǿ/8muS!Ѕ {x|/{f2/&>cL;sn)!wno1sSԯ#嘟Z/z^llLs/MOxN(u:ܾYH\!!sI&&mvsöOR\s+1o_+:7g9yp-e s=O;kOֈusDx=W.$׾}gWLr{2VKwjkK^*7QynmgwWϾ屎`wt~bnxTQ㭿?)_ǰJ|{yqZ<1+C~'ǻp wayS낉3\}|kMȴ ^'۶rEwҿQ|떭[NN={O}w]rSWTDl&)XZW~Vo->NYNu"fXtK-jW񗝫q=lL# +'tk_auvڭ +'* 9{wƲŽsy.J6œݱ;T\yre2Ocؚ%V/^ܳa _8ΞY5Aw)}ɳ8jON)X-0yz\9] 9{ 58ڳ&ɿIߵJm1 ά)]5繹SĎq=ۚ~\5| ~;cٺ W7וX@D T=tGim'˚]z"Nm/nאZ"={q1S}Hڣw3|\))F:?Y޷d:H# "։5?sw%ٙpOtoyA3һ.ez'nx!iorkt+not9.ejdsz G//wvqo֧S$tW:xPO'{\{RqU@)e-NLe6aJ)Ύ9t΋ULL}ߖ-j;13e4tKej? L}6k9g^Os)ke쭻/wq 9f=wЯfhOj8rucḽa^9-sj֨NYTBjr,,C KVwDlh:og՟y7ȧ~3ŏ&T4L{=s3j>~3¡t`#֜eAįʗ\q\ϩWiBG:4.~9,MM&hm8<ER ckܽЂh㷄[v~{ٹF%{ϔȤnqzI={b9Ke[pMJ|eEqKE[!h:B/ߛ6\xлG_+^O҉a +Y9cշP\o/;;6_02#ڣuM~3⑸-NJ6kN֚MJ7n_Y~?`vD`Pm͢/kf?:SaO~Ξ~̤.nSOc͊7ى.=XI߳+Suo#֮Y{U^Dpٛ,_OZ{^p1K5=\~Ϋ8RseNދn;4nCCr,vghu>ϸ[Ҽ߰`$߻ jbVpI{R̐2DH?Oʞ9WnfNͻwvvA[?;C&}VrY]I6*w]_/?SP=D[f~^ݰwVOelsnФ!] +^lg&e[Ǹ=Lq֙Re}s6>![YCG\+WOufℓM2ԫd/}uʹ+l6V<2uD$nyvӱqOw.~bi^5k3뻕wZyqy*9S~Sלڕ1ϼ' +۶9lKJN۞Rug}iwo,%,p/a1E_\ȝfgsb:n 瞷,^upkPS魍3YQ8&WrWRs M>e|$WuZji/j_j7E0MJ_*(mwF+mױg`ڧbg:-{9_g%9˶]vr?BmUɑw_WV[6n|[jp0*nx/驹r>S|߃ +ē^/آ{dJ3UOw9wb:\ N2sM9ߏjjm]ƮIi bS=|WO4xvmFm7X"5d\8wWGRk59fDh~^8GJڻ|[tY02/}׆^X`{]w=8nw[E?':YEbf˷|! WR3wggo7In~``gkVW7eIR_*f_w{R6glt}gg7{;~ַQENȏMNݧ| R*ײNOKW]8]qkȦo%Tn,,/l ?[4hs8&x=oVE~ +S}Ӭ90rƟaNj :z6VlV>yi4y?S&EJNpx}p">Yӷ473M~6 t.nz`g3w # +8%?e+z$qYKj{s"ɆZJ^O}}?G;(,r*_\3wew2O?W)^Z {oA* {3ɉM\}`Úo>A{G%.u+jz&OHerIYg渔TbBM[{=+-@QUũGƜjjmquIĖ^r3[޵O{l3nݹnY@YM`6Ż_y8y\W0Q! ݞ2AJJWHpt2wWd Jk1G"әٓdE +mwe=eE'uϮuߟyst?$9\)cy[fvK?\yrs^+Θ}iή9wf5^g;X<=Rҫ_xwyŽ[m-^EszD~I&WL<0g3-pN1h~6yjο'.? /۳q%l3bg8 kڵt)]aO{KFE1Jz&ߥ ť(y9wY:pt+#ö׾_Z(/ᛙtEʻu˾ow=nɏ)8ؤL/'nN߹PB4UvF6#qW6Wn|z}Ue/״ ZR37~'F!$!)Ǭ1+]:Vk +}Zlm)HpQJx@ԙ'͒^^ }EÇNG UEx=u1-V%{.Tğ/x_Q=:J7gusu,K}]pE!wuى)k{9+iOu6wH\aƢwkIu0~8:1m=ɹ_Յc{$ͯئI5~fP,9Ϛr6ypNMk]*{y{jR3%IHgU?Ggnjp^0뚀+SW.^K{K\C?6KOW;)8LMJ=.g5X##ڊʋ|Eg&$=w=VޔlLu6_zȗW|u33xoQͩ?3+]ms,{ɪ;8Je.nԒ- +5-tI/[jm8W(*9~{+iaS*w˼{uNo/![ eX;яXwKeY6,6 +߿_=s,wSCv}#f\w{bOlW'Dԅ]Pѽ2ߙ^rRwBc*-n^wf<'-js3ӋkgT ޴yðVa)mIKϭ+Wѽ]űy8\D ?X5b>[Y|3\Mg&kǧv?ր//_0ώ9bILNJ6`WߜJ̞ȤPᯩ3W̫ٹomRo{yVyM(,Oג2zѢe{kiwx-~{5˻^ybٛ>ur%9^m}BѪ?RִoY*~!9>.fb§m}>l ={CXV~A_nY׻!gE0db0=XԬuy5N:p?OYXAw+⨦9mdm+`)^!uL>f&oV|Y!| L.Ff2\)MǓ}/ԗW2,Vwzݤ-ӳen,{ލSlٶB60kpjgW/I_6 x|k[C#K:O^BnWm5ʙE5ofip _%h욵ڢ>mqZI䣓_u= x~Wb{91_`a+;EY猯bj&-QXzOuO__ʺͷheE$Ĉ 9pI 6mf,+Ob/I`]cjT?YL{/Qe".ٶʾ|9{f-2񭐻LBW=ݑrl潂;?l \ *9bGNt6Nk.|Ow.2^:iŹ\Ū}/'3uEeO9bcYLM͉ X=*SxNhΩdc#Gp](GJO8}g1k瞲*aWxu֖ +lnG+_!F1] B+/:YPDj^ۤmd/]5$[S,aP¶!"k>V{uکgv|_E#Xm٢,_;{]ɾ d +[k)*Ek{!*dٖO-~?mI)<~ȩSƒ>0^K۽DGBSdi*7s-{yQn8y7۫5-YW$+j7{牺~UsDu8oԵ^ٵcvaǜg?\d}29bWj6E?>lM2Sj5*My([ioE܎o?Z'WwVW +MU;ݮfڕrM@7 'y\ߚo-~p EP3IljΣW[_˝-d+Aϗۚ&%-xEVUMI/6ɟݧrئxԲ?Wv?g):sfؙ}%m8 'QUdZK;b4mڴTqb ͥ,J-;\sCdѶ7e)ɳhl ȡvHȇg߳KwRI_i+:mӘugpc0eGy=~2%U]jYgx|pdRY;4Z3TJuezmo;JV,\|*Xr^?_%"\{i'>7־h%9M!v*AX ^f/ʶRW{|i}gIj-=$:bN[ї9 8}55ʆ g|+g?w3lMV|ȟP~Ry2%kj^|tMuŗV~#drg)7_Aws6E\1kc3;.MjJr_|feo]WWdծÇn5ц%,~ovα*=cҕL}qr뗼W]a̾5Wm{z^ڈ+ NΙvNO%總~L~1g'@ۄSov:~YYe9'|t'*m FOg+>(;^yɂS/-nQRo'WV=!B`ޣ-|5<&D<]g +ݤ+U\gs[7o_M_%X$qO:SG"e:UμTb,5Yz w]fYSYuW,.>׷Ϭ4Wsەʏ]+UW| +7OحrJWTUtJI;8FğFLJ_NV*V8γ/osTqr͸wܿIPxj~57/|ڱlߍ'M+WIUAE/[#-!ܤy{:?Er,)hA?u֝}3LSL? 7O/qmi7ֹf=td?`yqeƆo߯8N„0-q;O.mK*bWe6~d){N8]>W'azuLXޝK3>Sض z.鉤V b^K|_uO:ŋ&+ɹll)d:w_>4mca}}~7遰 >xnv:; +2vݱ!dI\5joq=ոR~cVM5>s׸ +_)\])pg·a'Ql"eU"jqn8PeP~Y_e.ڿiѧ" _gp?<]$ik--N<]{OQ?x{ȣmJ'1%>۳qcVͿeS&sIz8}I˷A7bUׁ܋5;,֟^KCƂܝ޼-w˗M[n* MeVXxeϜ-?KX-Tb7ݘ\{Y49S $k9.SwK[t.]'V7{E3=}Se_^,Sag{[WSxo| y*Oqgqm槭,6k*qtG.yω_VK|?r[I#Zyi?_UI?KgoX,L7ZϑۻSMϾk:>W*ʚ 7~?İ,uaɕ"SJ?Ll{`7nɫ w3t;KL{/,Xtm(}:L? Í ,,AO^S/HO}7eJ_V qsr/dK>d3YnGj +yo +x(!ͮzL1''rN]2a%nڅ?>?ػNu/bg_;]o;C*IbF}&S^ v}ux8^_23q 9,au@:D~r9 BVt>շf;vRu J}R#_<՜z +)<T-=;ׅN.,T376p8}ɏ4v]6InR+Y^kN~bjQI3~M%҂S{79DR뛗n&zIgK&KT4]ԙ\RY͸q_3cv} xW=,ݣHJҞoK:QZ?9Ec^d}3JSD2y.̍ԊE{u73(Y({nWPyg.YSen= =uU/ZZy߯s׹'Maj-uMXPhQ߯gE,ytX}d}Kܖ;XG\ gcJ_( +;j^C4cr7GOYrLb3|I*h&\Wrs- 'іN>w{'/쾾}Oq9gHϿ)K͗㦽{lEر2G36T:-n;в:/O<!s +8T[$:C0Jܿ~ZJnhQ=}d 6e^{(⭴D=qwv~JSgv?OV=O, uӗ?sڧC-jϤ5ݛd9 #Ӷ_iƱPojgK\k[3?zQ}"3k0ϟnǢGr;Vymw<"cw޿%c?e5~鍒M O[I#k^ΫOPy!wŽ0>ɬ-*+ۧV(tYc|eCV<ϖzԻ-4C .7J9o926+C]"ټJ> +̺z}VS k:nͭpogZjy߯w \b={/uML(5w E&ȫD)sn_t_lH59+>Y ,X߼ȸqWvp ,:*8}z&Ku5J=݋Eտln4܎w~q6;oR?hqܳϟ)=(R%oѹkޯ=Hg tNf-gV&o|IaNf6=ҍfqZbT̡Edwh;sIKXM9_&ku-G]{me9__~mӡ>Vove̶_7}WDoڛ.8Qp;2Dr@?v-Pʸ}:g'_ã1UzMWWREnWoq[*<)N/2NkeV-=AZMk67.ն9tfbsHO^{o8>J_qoszY?z9],:17G~ǼI?K'E.mړ}!Z'sN=bc]bRʒN]g|9ةq{W,*|wY?/E[M.`Yf7X'Δ!pvliGbŎKfݦ91|h/x$1PKڕ֝S%Ffn}y$L5gOvi~}boo^!O~Who%4}4_GyǛZO:-;!s#ݢ]}M{?Z^uǥ6u|NzewEw-.m>PǸ*&UV?WI {"8c?Ijyŀo;)fӽb(ޣVW0qgi _o +|\0a;{ZzJrDnm/\ +>i_v.kX\_}޶,ڻ\#e+Z:'fUY Gӧϛx͡Sf(q}ϒ+Z|ƏL3y<拾۱9uW/owLdB ͉?+ݢne70ae67=mw66hHhn?Nۏ~ywN/Og]YP$45zhզ=}ﶥݺBJFދs_xL\qKnrqIsW1jiprWN}mɜꖶw{=DMk[_wܴݲU/{lg&l~٧N[SYmsԬ~ xBm8LYynsi? zd*Oy% GS}7O>Qθ^S"^ m3?{w|u{|cdf՘pK$QK[&2RRzʎ" {;@!qЬm-~7HϮjF:)19l57~:WcvE5+ޭ=EǕH卾Bnkf ٝ)fH*gw+EJΙWg.~Lyܻ>_scR9ִkIC[{zj..,?.֦˼},&UR߳ן9!AI`[֖oxɴL{loo#îX&K~٩]9#0Qc_f_̝Jy#lݨ)e-Eɻ*߄[G粒^G*sYf5rr{'/LݙE_eDo&W9 lwx[Wn[j.CߪI;dx" jqY1k9Vx\r Ol7fخ ͊65C|_I&&L.\Ψɮj|~ZiIi~zP\9d[(|x)wN ,|T`HAߚ.<mX}V w^ıo.Ԫ-:: +-i87=k 晬HsKM?֗'+#W~GnL*K=46}YwEG {/]xw;Ĵ |L"/(ΚXsSϼQ!5~rߪ@B▚F]q.DyrQ㫍ol==//g )8cRkۑal wu7XuMI]roFi6Tϛ)zmEJX7앲矠>WZ j<@3AnܶgW}֐?_Pƣn؛.k )?\wD!zO|2P";nyO~cIs~7t,Q1벜6M;aJY;ڢZbҽK=WOy+TZZ jcݘџa_WM_׫ݖkZ( lofOCߋԖY55?E#&\PWrIC9ʷW/!pbYM[7z'J~z%nr݇fh-p}ź _طdx>O}c)u+&֋[|Ʉ9LRqtƭϚ>2џvsɮY6酦cX-ʟ: lCVCEW獐O೫_6}^/[o|]ggzK9ZMhufWg) GE/4{wbtSKK¯D]$?):_~aWلni߫(w.x$I!'$r$~fhvFyPi{al;+L g\DoN)KIIq_ִ,~ާy,3opw>T"wև}t̺r{$\k}s{9'ܼxGBE=E7泯t*ұ|h5d=^_*0D9w=,vOKɒ"ۓ_vr{H`:+hi+yDOdzw#;:u v:ņkL4zoϹ}W^<S_YiN7cf\c…XؗPy)'2'+~U5xj30Rp~d}ò*jڜmf3߾T)j_Q|U_~so OG;YXϩG4%fG;;%)SupUQ>0|w|iO2#fJ/(!q1 9gON fS-6'<[W:kQo& +uYtНOU@8ݣRg۝aQAg)7WW}/eJ@7D#쌬2S?#zfނ 7]-Y(rɟ[,yboZ /5,ˉ?{|kSѥuozٳJxr{Ǣ˹(fe;޶_x|I)zrVt)-x-r9eg)|0eggZǸ1ڕؠ|BǮFO~5;O~+w\U~:7٫ᎶAgNpԾ.eJ5WFE+:Lߚr%^r,).ݕ.Qڋ=f_qYr}fXiթ+ZS|WWw5Nw{iGT7M;kyc忭l wj6[#g/[SLR6mLk[ϓק?^b+542y9T0ƇVqlJBROׅp.Q,":O?MU䧟|jswf=;Ig un\<<%^-eo߉:{.G[3;Ub_>b݋xm߽¤{ʦîeә[kmyW3q]=Õ,ڰ3wt%ٙ$9;5ߕ^0Q~*D/qY\jowiڮT9*?;9vŚB?񇫑b@d Sa!ov&1 6"}J'Y4vX#¹">ρ|8>.sOޫiyud5I.#r95acQk +G~:͚~[n]CɟR{yՏ9;1_h3k);=com<*24*T`޽fV$OwTd0<[hw A ~Niz/ԮǹOh ̖W(sRaRbR*Y\wNTm[p<;v-k"Ʉ5!Mr^Vگ*(?]Wo9n䞋;#46lHeo|V.@7t:+orf{ks,%]G@J|߫%珽rTsgevE}2J̵"6w\ $'<=37)Ņvcm񎬀o߻p圼e5ƖMs}-/g^<Mհ}~z7)?-J@ VWJ3ԞVcО'ͫky1Sv[k4\t}D+Tθ *edٖ:zx &U Z__pJ~Ұ̛ζ&j5g;%V9¯~˕!`jM}qMcno߾5>|y+|7\ ]y儘u;t|2N坸Œ7 + +yB0}u͋&Q4YmW~L޹IñLD<M{fZdΆbЧ'kʌob8vҌ?1soνgo[UQו5C1ZE#=8ӌ[|}N@782&p}#zܞF[ +W/~isVMq;Ŝ\yY\`ƿy/=,֝-*iכ83/Jvay[ӝ36=00RnD [YVs'hdnw-j]yǚ\~gacf >rgWJ|ԑw'꜍v݃3ϑagDJ6[Pg;ն[zxי&Nf:o66:l]TśnioPnטr>5N>j4:ewZg)pÁZcɭ5XwsJ]Q[חF:gŶso +pxghO򉿟irmRJymw6Wa`Q?QGGz7o߶ rA}3=5غGyJax]0e|̯Ke׮MA%pY«ft!gJ7 +ho gZ|@?>x?2ݽJbXSTΔ])84Fj햦/K).gZC0D:xe=^r+S$Vk^m/igzy5[W0:rmee e+P ǑN/&1Rvm=tvƆ>i|D:o,3"-wo7itZ1iV*ާdX1JmJ]q7,Cmbek*MN)XtbF/#lE1Zf$/6tg\j_+\7i^i>ypf}[;NL\nPŻB翝<:+kbvpria+7\,{_fl,$dUx'é{oUYNK2)Q?.yqs;UHwSlKPйfA>۞.{(=-W&rv|1R7om/^U[C<_e`meCnC"2gLc7d1[`I~w/R5/no*T96d-wO̜ϙwq)͎X:3cN+ 4˴glv^Ck)+g\Ԓ:yX/MJsTR.s]YuxgԢg>c**N5}g7mF{c}5iyEܛ\sf5ߏwY17~?3zƄs+/Ӌ]dHkVj"{Mw4nlg̽l^=ǥ / +dO,76gՃWO;MR|ϪVhg)}]4%nc]%L{O+^}{:ٰZW2[kRó Q/jZ+;?@^Ȯv &^I/>ޯ?qնwBd <_utOvnesH>lڟ G w1^t;o]mAFjxqZҶzW^=+>8ά-=fBX8nU:&šR'|"q,=",yջgݱY^ɇB)?iV] ">,ω4p~˳?2窊ulz9MLK '^1yU&yVtkB= LsTm:{9\tUS]^wx߷=+X]E?&w??,i!.N/ ?X7&4Op2>h⥣ +ϊ¦ڴx[o+><[,Q52 EfO~էτry3w}b_ٜ[nZ^ؾ͎I{>6J)݉~o2+gT,[髽y:%Sp{F%&#g4*_d'#xGޒ/N޴Gv{,ݒ'J}f\R=u.,c:iӷpZ]51/y&qd"A+S#7u}1n[!pZӞg':rO}KͷWwwG9ӓ|D@ÞRZ :00Wj}'(5z=dtO#׵%{c b+ZFO5:6c[Ӎ6}}{/LR#_ӧ/AŨIw+˳<;| ]tEF=[ORvN%',gj/cOy Zr,edLoE#p;՜ZxundHݗ~cScٗAbvҷnY}gζ`8 38}?sq%_Eߔ X^|8{Y{[{z6\|fşSedzNk6I\4y2uY;\:YN%+\` m^.GkFă)7ל=tҷΧvO]5?e?dzTw9%-X_s>-k4$iכ3,>Y7u(' +=(hUTt|+nw ~kgw/<}Tnj!Lc njUR$e10錺/V'h_U)檔Y 8XN=?_ƫ5sGb!ܒkZ3׈93<. O #ųpz +%wۘ:vG`E/MN-qY3*SxdF>l\1j}  YgǼ ;[qIb~whETɴ~Ls3g֫h{8j;uv9vU\NSM!^k#zyodACߡ"<:Zzb(3;V k%x4 O˿zi|4I|q)30 ?M|w,vWXKLV T^b)]NXYy+ב7*+<8ZxS/}SފV3pn%=3׭ILWʰrk9493~.kK3M1<]i~גmoMI^:5ןMUTOu+Pno/%~z}1|ޟSNZM\ x;Rdn#gSxg*֒gBŧvn>fWw}QT޼V+h K^Df -ϖˬv.?caWew޷mcp{͵w~;7ysN)KZ"[9fyev9In{sj׬sE>Cb7&'{;bZIY#w1{ gj=bU`ZlcdԜɿ-UTNh嗊-kn`}wo-?OuF3L [vQ|ץwf3Ғ^uzQa>ajpk՗Q~-<_Ue^S!ɽ0G%/wʴ7$W &%Gŧ3J6;k%K7y/ Xs5Yߔ`xT`_^"Y4ۆڅmz(XCѷOO/șzk:?bo-\ʧg5~vV/F#bYwg{TTKt-X)IhbUGZjoJqr kRK4ϲUo'uj ctuYi'tj;ET>Vv ^S7|E-xR[QSnƈ介 +wPatϖ;׆9SO.z ө2KG&ou\k>wхKGWamrn[KX/eX2v!O^Lei·VM^P3ˋ'Uwg X30p+{BUQ[aPTN:L'v^~5{;R>sΦ0 ~z3펛yz/zR5C;Oi>#V7lj#oZ;< g"{-AUfGna|\N_-,}=Ox#/25,ϖ뜦wh_-kN$}[Oa*j.Z]|?2 NO6i;s/՘M/wյ_mQ~F7l'2](UjI1gsݷ,L'˙uW6mJ*~IavOhUlI/.rE.Qlx}07K_L +xOx~A}I){m[?ysjsEf/_rVfYݙ=rV}sssyy?;soE^{BTiFH\Թ咅9/tZG:O&F?>sS%_ճ}c%\_.Y:3W/P?o7C\NӎXv/MuXyt1eLT}[R#cʻEN_/q,c+Z?}pCM7:ODtURni8ú-kŋ2<&=,Ysoo}{qճHngzڋS)sρ>R Z=7+ݱӯYjMQ EK.N >([:`y + +O?U:oь;,Azk|r ə\lbaK= s]/~/;{Ymecg;5A+"#|Olq~2U4*̹-|4g/S tX7XNbܹ9^yGfIIV}-wMzd뱀oW ;WN2y9gO +Z,vlϑEn>{\=԰7GE^{G n)}qM +TkA$S< |7wyźzvanJ8}icDb}k/Hgco^t:ٕ&-o/a~z^KZKoy3z=T!Q`ʹNjgusU'W hep`gEq',[(sugw6ĉVoo_鱒FU] OZZa2<+$ O k5YcMrb m{.pŷiݿxoL;ή3iKsÛmW;trŒ[G6q*Xe:#]370J uljuV{|6sV/t;]נw%N)̷~4̿ť'[zWZh >~㏕̧>lcRʞ.Nj&*-<`3_\_! /sIXyQhR][Wn9XQ;`ew% WpJ5+o(8P`|'-YwŌi6:M|&qOYvϾFOL>]vzڪ_i-Kd]=vMRx6%cYm{X5ii/&9yT猆x8os ,T-%[U'I19-/ b-~~+ou +wTvM:Ɖ7t+rI*Ot.1bVv N]%5g>6SwvhEOGSޭ0-n iS汶򵨷h$͐_%>Vh|i3y]ms%+$f<ӌ}MPߌ5vԦGJNB36knV?<SPws7 <ʻoN\(oewg>(yTG#%OsX-M=N# >w[ʦCn9~8iǭ?8?ɸXK0/ +/|yejN9SǙCjg]!3iJݖ.,~!/]6jǷ0{ʮ{oy˥mN+[9Vf?(m&<#egb>˸b7Vl^x?#L*'9x=y5Uڋ3bu,9~q)n9L﾿z̥˻&<+gb8_l֩Wv6;_2WбZo2>=#|}%U_R4Y.Y-Ep08gX`8ώ Lֹؽ]?A_R5\[o~9.hcI(⪶@FgQ~hvu.2 챰YW֕{O&7VcWUK,\O]'ҭ5,}7&گR1q{cY>bxK(_7D'tn1.4]l [N!o=S+zۦ'ha+̟k,'g/)?p˽&,61g{#Im'-`X}ry~]]<)gĽšm&qn٬+缥>}>I1J/L+qpK8pn gd6V :pϊܦ0nJ^}ƱWjnPVP}wX?vc=u٪y{n',- + ywotQ٪OSnthN98w֟umwf寸/OcLhCŅ8jn}B 3h9{zm_L)֜b} ʧ\)h5pIAw3ߵ3 <iX)A9ۇܭ_vˣnn3|p27y߿?WMݾ%OorJl39/X\Yy"eO~%e5עvNWO^ؒ7&'YnROVxE~V^Y*?huSQcv 0kA^wໟCAxj͒3<%ΔܹhStG/ "Knuu>Ls{Vs=wR/{9[٥5Y`n5^V:}ka yi3KVm[Ys/l#W'Vt|!~~t7xXk}GfjO-ܒڏV~_맊~c4?BZ]R̟,g7o~͐ɖ?c{\yl;w[9o^ݸt\Z3>f03{\bϮG^8uOڮByIͭ_St +X-sb8E(i߽/uNwC?{/MxPQy֢YΛ,.Vm=U%$6_pƑrڸڕ?w˚fYuֵtXn&1{\Z~Q@麅rTڞh ÞxɷK 2^Owvc{h]MR=36dmd}OcXPù)-~wwXweR1חfG['U}߳o»n_rc7ZJ(Z14n8d;EM9n;ѐm +k-똾ԯ0Hxy\;y5Y)ܟΙw>jG3\:qդy >qJ |SiN}<ik} Wɨ'q~68(]<8a +Լ([ϝlgw!׀ԟ,=n{s]C7_tw|ڗ{>xCIշ{}+fSJ罚śrߪּ9:B 3Mç=q0`o5yo)g͕[sNYk^Z|ղ=YqI'?݌?U8-O")?]g}BaR#n /\[ʽ;Ϥl6c}O&/^9]E=wYJ E|J7y]',o&]UIfQV>gw9G㥟OJ;`Eh÷{+2sMaǩm&_SXrz#SXx=- Mg|̶S u7e=YHg)WoUƦRˆ,[nɮ3m~luv_ۦBsj^hքڟZŗTLؚ&x¶3H#; ?<$Z4-rI;'[fն)G[ G=20z ;n0fW[}nUhۓ¼.LXu*AKќɹo?fiO,.9ڂk..=[T,+̍wqMYhi>۠J#;.V[}fuWN( ͗)3 +79oܦ] ++9rjypZg>ƉWYKtja'>(tq{1 ߹}|Wμ]5d|5,U5)tUa>BG +j]/zTa-0echo[gã_> QSTԩ7﫦slYP~'gI~]bߛvۄqNyw/䠜6^.^𯪣t3Oo ^.)>lq܇+>M,@deC"O+/zHߧYY5(uoul-qE3vtl'n~L{S4Yi"y?U.YofRCﺷ6>s?7xzf->Գ86]?Cq̆eַS +7;<7DW(_5Ƃ:霷 S,6߻A7OG~Xsupٖ{.H>wY_x7lӾ _dӂ<ǝs'\N3Iu^^??&nw@UӇV?|splsݳv4k|w1| U*t9BʕU/t{m?+T],:f\ڑi&ʬ_DvK +s7uE'K왾.r!8gyAP hҘ3J\ʮ00ߜ1i+?wnoe9ƜVWDoh~GkYCu-\9dzzM7˸y^m#0+Mz6/Tv>iR~Ȩll%a?M{Y?Sf¥o49Mi<}S2OL6Y/q=\'*s82OM]uю9_nvKϧvҷor[V]9`vWg7\^iz vYp͉pј9U?MYɗh$i3s_IXm"{Gacf^;uƩSź_8' Dz7<<|[Fg=]z˲7=YudWۡcl?}Fؗk](,~B&|a=y'v>uΑ#w,< %z׹^2/X]Bk%y_[ʧo׼g]N̓%ͪ>K%ƄIgrW8w}Cc?eegyF{wm) /-G6Yw?\pԗ} \Dڀ[o]xw_筟hȐUaU 76j|.)qM}ŵW'uжV[YcŽ2ߟۘ]ޮs߬;Fg/iu[; +{cMiĔӎvqw.eOuثk4gƻkZi,*eRъ5/p h[־n'> t76~9n >v^1K}<;10~bWtȸiu񑼳k]7;fyʶj˪1򬳦wnj9W5ߘf`bQƢ/=g%zၾ9GR$Jxԇrޞ,Q՞G.-~”&"* ={zߺW&o ~:GkjΤ&C^X`)oqyN*\o߸,W [`k\+ /39'7KiB[#z4u63WS TL* 1ۨYj4\ù@hӏ9lgZ'x{ė[v`禰~;/.9u7(;z M=/Ҭe!)]+~[ܽSGǷn[.V}ze׾;. +}wUU_ZҽiZ2k"]V^T;KE?N Z3OTe/3v\=mn, ?cɃgoq1?*8Y+ϷNKG^j^hKQ7P3sзr˽wq +*L|j ޅ& MXx̮9R_b[_|v ŹM=3uOeDWEd&^89WOYo]VsIO53y+L:tq3hN;3Y;6x/y˹n#e:$ 77~՘_:뭾QgMy!K/z(ۻn?M7\&wW/ ¹:(57}7tەehNz kEOڏq>*uV%N{`f4cW[~yDboK8hm;\=t|hOV2\>'ckn|?{ +CdS'˦#P/o3\g,_Z+iez8Kq>ѥK' !}EWKyb'kYs˟{<5M}qH1r﫩<*1ŗ;-=+k_]+:s>%6-Y>哷F)ˡo˒W9ٻ^\tWi/j +c2O>0bc?Z勣gDF6 ߻<݈-)`]mS{˷mwBb;cz6X*r_̼/|\R)?ڪq.QH~fnh"вj-̋1*Ud(7FkdӵǾrjǖ['r em!B0OcM- Wy> 3u[v~OfR>IJO1~~mbqq1ӃYs_ w0oΟ6Fs^їWJ +ӣ,Qrsϯr3u zEQ3[m޹Tljs3Fu zO>%Wƚy<<˥xC']͝k1ʭ +X֘ήu#æ[Ej ,zaR-YuI?1kޟYoD|˺˩n_̷5rMBκlx[Ί3_n^eqRKe(|^{O~+,'+.̹’lF[Y~^ic,ysĄ' pn[+l|G!,{0ISr߇-Ev']R3d /?n7?makYS0sx5GRzOZA,b6 m^2(zy.ʷ3T]2,+ߞ+$2WV&L9rv'_d=Q;wgO|εI[沛,E;Fe>-;69=wrFCy}L3or>J7<,hSci[ lR"CFwCKSE*6GӬir\wт:ov5a&V+G5:SqM-\qm +7 "+0?r{>iwf j}.YvA_RgoJe͢;g.0=wLS}3 ,P,sÀfk^ػipU=ګ{*cEH +ztS%;E"ܱk9K{Ţ{m1qqRV؝F焷/81yKw?ֆ 9MZ{:˧?#Z޴gf^)d\L5:_by şNL) Z}EX$7]Ryk*Kƿ/ ~)볷eϜu7Ut7gƳko9xݵ'[sLؼ}wixώIm;M:f`8n/]9\TZVڋʕ=_c]-얳dήvތy>%Ccg ˘l~lkX*WZ2[ql=]C{T7>v03_,:=+=Oo~Iİ<=aU)o1˦Jؐ@2ʃ 2Z! ~YR j;߯ ӵN?icmoĭ" ֯R"1oGnƻ0͏5wS6elJ1uv/[?Ū]_U_֫֘Mћ'ԟZ_xImߒ65}/ϛ_睌ߝW`xmUvj,UÚmޫod{vIVs ?ܺAm͉KYYEDy{ފ s$s'{|i:oKSx6'-w+n1:T~@]wn){TY}kՊoP~\ סo<7(qNZny>ʰ.e*T_fPLTO}΄<>2MPVm,g +5? ns]4:-.iYrOs?MPp*:ٷ*^pFx,''i7&߳`f!_e~{gc>L,. (}g}N[uSNMQIӋM[4.O/)Ov-r8#3w^_/,!$=וwWwc:푛:]{W9>^^3**\l}Y&%1?39^Su8㶐P7 +mfT? ;ƲgBysPI4}ѾwWOwz(qRiv̸F}W/Z,;!6&Z:v%+ӳIw0YNnbYpF9Us _xw|}2'$f@oǖKqS&Oث;F GffCJR3klwx̧CLx?9#5wJаa񊩟U3Y)-7n[վ'k}=Gs} {Mdg] kxwS6, >gն{&<4)2F[皉Z&\>˵܈;%pE5_T⯼KH1G'cmy⭛'"_I]pݷ]i٦eS[,GTW#U1lʑ3ݏ=+~݂R+Y[~xe?{jIӲn:AB݄#;kCv̺a>>v٤Z}^,|ٍy_&YQlcwk}x9+f‡Zũd玾~e +tu}sYAaKy ^n +=Njnv:SxtHz,Fc?W5lѫۿmoʎYåܸi17B>+]_lt$Af>OmJjю+eM<-_߷Ļ>>:LY#[P7@`gLۿK}!-WEm?W뿅V\Iblڣbn)wIIWWvl(==a^Uc[Mf;4"KE&}pJyUNZTvoAe0_$Sd9l7ϝTb텻7 +΍ϟkPkb}~-][*KzjjJW\&vGʪ BW܏;vB]xr|k5>}<i?*\qRn򹎄8I5Lv'fp-yMhN^V/la83[/.O}[zaZ(3q|CN^P3n\";Ȃz;'iv߱*}Q2Kݭ9YU |y̝u㤯eɓcu:$ùC-s{\%՞I;Cٟe'4~({c^\*;"5mU{NEN +YbGF윱(Q7F0> rwuthw>[y9-;u SfOǪ%GWqr4 -~'tla cQ&㺝p*-+­kmo {+gǖv$.ș3frOK:xrvÚ{-nNo~3=sC⪿]?WzϹ6O-OGV;+dtCb%CE>A=U.H\^lPvZZ zq߫t6kOGT.L_dڜ'}{k `x@3n(:ҺiW8o5x)PHpG=ůz[9拾֦I:p kPSm/xe7 ; '?}o{ƱIy_6❠twGl\*џg^gz{ҟkbA,SֺpPvre)m 2,5ΦIaf,gp_ + +ngzii\irDk s%g Ntuj) AK. ƣMT&kraຌ +;nhPP">V!~^7~G9qV N\T[xm7y^(lTQ6r?ݯvPKym$^^Lgg$Y|< +BEU?<&ě/3GMp}D7[':y<8+pNB6MWn{էoB>/ 8qf;%_tW^?k#U)hK6k^)bAfS 8U܅M,10z^%Ev;g(W +#~^(tw(bf[u憎jdM_AlHDgMzWk;5>7?n9Pd̔1oTǻo dOZfʻ| >H2Wf߃K-2͸|W;/l7dW-Z~Z^$T{<ݳr[{n}nX}8%=2 ZibYaWϤ7I6/8]4EiS~\kٙ#U/}&u?>6+ǑW}Zr|Л~D\ȼMSe4?\ôxfӘg8.w2L[z{$If'a%]vW:]ŗƟlU0^rѼ(K7Ur/mZ)aa?<ϢS7/qUgdV-Uq%\5^;˯=;m+hFhSX5ꊭs@;#.-~QoSy|v׻/u܁[ֈ-n| |&+mY/DrQr~#bo۷޺`-2-uӮ] |T\.1y/ͼhz'wI2}?]2⭯mn_P^eEQ,?b`</szQ[W +,k+y*S~۾< O~v(㥳'o|9=mOŅg9{:f|hZdFKkhђ¯+, ̙{(1`{;o9xԃW4qu[L]{ lAN@CW&w-VzkR?b8+,.^2kh$C\f7OrOz뢽Oڤ(%,sO+{x͓쨺>IeI~\ C8Qq=[vR<;Υ.T»ÉGLGKιE3#|V6FFTT5q=8nm3Qc^){E~,<=]oM4N}Vx|'5]Z3=HAn 3.{ޛ)S^Jf.Xs}f?ʅhhaoJպev@Κ) +GW05rk+׊u_Ș)+WйZ' ?WɮS6rbī6ar6Kq*U+v{3dmP 0::O&'ɾ~u]%QOْ +Rƶ#W?d[UڹM|@ww?yy#Fyt'{ %Vn>휓 +Im/_^sWnGe߯ͽm~]dX[G[-d49맪EdJ"9h-(6)J6q)ߖm¯oNbgMК?;ݜR<ضR۲U{f}(Ϝb 8GѰ..8iX0;Iw9X{a'=EAk:^r5CJOO?ϗK/[/ٶ|7G7^^pOTYd9>[U_^}TdvUg}]~K{ЗֆU&k^hue ;bt椪OF~VR u7 oA#6^d~*O_^CMx5Ys~ɴcdƥs3WIwd񳾔o5%#XMPNRͻ2a3)Eh%U˙7Z^);<|&{˭Cnמ齖)Pߗ0]};k]X+_5eGѺKA>N1u{Ap%q^st%{Q]&I?b Mu7ʵw^Y׋G1U?4+};=cPĽR|õiN>2v=ߋ~p IjtwC˟5dû-v^.Tf7"n~#|u*릀*6GU[>:fg5=cvv\)ٲXdmO⧉2L_2]q%ףO5[i^u: 1ފ\e$VV(':[}E+R^wumŏjHW`n7o|a9ywzKe&17HH|}I`^:*m1Y, qV1ySڋ? +rҋN4?)hq+- ߢ{c ?99l@vEgM%/Ol{!B)cwײK,L7Ug +__2&fI] c8K;O]?=Xk#dDttsZ 9勬=,6_B7ܜ3jMʅUJL<ۓ#ם{W5m򅥓Oi_+"Т% A!N 4Okm[^+~<ŧ_?Zp3㬘١4Rb[:DકGDyfƎr8$N\].%Qt׋ݗ2rEྺK&6bؾ3KO\jʭ@bd.}qfZ=#ĩa]>6py봟'7]V3}f/y~҃sQ,~lmqX&vj%]~Vn^e2U>@†BX]c giulSJ,5iMx(v50t% 7>? ϕtYR+ּ]j'>z^ )Fgzx}5.:"hrpڝ\rI~\^y'޽P,֋[>59,n$g:4۫i=w| :ŽgiξG +q7{o?FO^HZCްo`_EobikP)ӜN`>xY .k9hzʢ0HK/wy4wZÍk.o4qv왹S{VY+T*WWr9X[^6 fM?\(3;DdugD^]5ת[_?9˱ ;l:!o9yӷ;YA{3LL~s|RXלݯNe_Rڞ(^.Iu.|?[yK݃BY諸Zxpr>oyWĤM7lo*?}m^jje7hnY}ϯ̶D%¦x ӳwQݭ SkE'Xdkݗg?vZHu_*7y>/]͙kt8sPeӱƖVKw^_~w{_Λ.ˢf< vUyK- |>:.ԑe<͢^z%w*XX/)1S{=,Eʿfʻq +Ζ;=?i)&?:h5~ٹ2PYǜl/yyϖg.mwk``M%ߎd}iG??"OPIlV$3Xmv7>r㏮@!:J)Uz̪zR W +nd|fK}|c,Iis75W4p<=r_߯57Zf2.X*=c]mTޮ-,؏Y&͚n,z? 6 fk3qW4]ܖdQRHlCmӵ_^/n>wcUCrLRm*W/_/3b_+ޟb_ʻͷ8XݷtW(Asye$%rVg֝ ]>l_=j#{H`͙Kv{M'1rS9I#A3w4xe,7Km۪ߘxB?{9;{¢+w̝sFskFWJ_ɔ15ֲj_S>u1MvV:[1kEOsⴝ-wĖwZ{Y@`~}/RvθA)oo]V;0YG꧇J^x ONv +xurNBF7.gv ym Z*{sBRȱukxk;Snum#:gcGk͖e]~dcYuL{]7~lgwħxًeWOfqlDOshޖyOL6YϪ=%[[yN:ue> |N ' +:|ɽ!?K|3?Y"»OKuٽQ}i5oUy yog;S+KΌuF*>_m*hpqߝ0'=Z¸&X+3s}˓:d6VTW\R:zrii_l|)~UK"TVMx?{n6H1![֒UԒmώ{ |ӗrwPȅM]-^=õwf4}ǥVYv7XΛ.ٽM3shlaՒg'?<{WF;ZK.ۺ gMZFo8^9}{y.S둌;4gM <_C{){?xD>ufKy +ae&.^kvl8Ekשׁ!J9aW[ B k94&?1gƩC~q:^:<^6uaTas4g5:9z}:"ǕˊJ{uijIl\_[odLMB֥ͽqsYuN Lh$,PVՙ(-n.Wu ~{ w]sJTa%g,N*2ٻmI623<+m9EKuk~XEm\WVj]."޹,Wc'p}Ґ#]_/cS"/tvFvݓ/nUP9aYW{ߥGWhUh Cܐvޕ( y}u)1Owxǵhuxs,Wr6u /[HyyN,4/j_l:~2-|4] +٧?8OE'8?,p׶YOdNw:KKq <ݛ?N?#uK(",;d+K6#NƵ9۷;G7p}_ bW7Y^s}ԊWmU>3լؿb]zMi08}J08tZ# >:Q5~:-u4`OS8;KQzʬF#3\ƺOL9웹8i+]9 +?=61G!?3ܠג~u? Mfc|$[3~;cc|f)gf,| ғTlpU>j׃ +c߶VTozW}IsrKZSs옞:QJrxW)i*bQqaݻCׯşq‰aҶEǓ XW%Oٴ}Wo^M>QW;ąs_fߺs῟>p!(ԝ蟪΃ӔXWHʱ)K?CM(j!vVSMX_p,1[7Ym|wpTVzlinVyDXͯq;1woCI65BoI]i\2F'| e:N(0?YՑO~=Wg~WI,,Ugu] u$kg&ߛw a<ݰQ?[ }{KԮY2Rx2 :>*~_I0[k w8f>)╍{Nh4m;]Wxѯ=߼|>JٞvZz j տ`73$OtR~DN.<.v㦥?Mx$SnZ>\rsPwgLFŝmmm^һ(PͬRg]qû. ¿YyEclUG ]MI淭g[N!?_Q;1[9~{P~OQÏ/[L":VNO~6Z7Jr筩'eܗ}')~ 7bc~,OIgn.Im>{#$d{df7v}Ynu/~4X~xV퓧f6۵+n#|2.z_b]u!c㲔koUliq(cޭV:|CY BlK_X͗Ӷ `+Q5d!G W*_X=Ε"S%~{qsλY +goLzWez%> +I7Y\"!ˣx\lf-zfWvZejO}0tşgXw)ZP_Q~Zi-[]J*.geLpa/ZskCcu~OPVݽx%,p4;.ass:i7:VFkF΁ɬ???_|"=4"c#˴iK]b&|~OV)E'lM(Y}~Ȃ5ggqFb}3-^i`W_<{uzLx&jQasCVie65޾z*%W9'w/boD|#,bPUQzḦت`UΒ;E>i{]d)sJ?Oy5ߎW$:,KS߽xro<`&QU΄UY]Ey| J@WR'Ht)W0Zuƻ_weT|=nɼ$ܛruK߻zN"ؖYzi9_.۵ +\ 7|^qט~{7hI/{Č95m=7gQvi+qre`ץ%?_;9+Ww[h|zCltܙݛl(|n]'K,W+-LXudMwKq.gXNmr[ֻ??~J*^`17ų-}4geU8 +OOj;_ڕߧ~>r_VS7;76n /*0̈E1R˞:sӗ]WyWmYTչޖe' +<ߒ{g5t]}Y+giYVv O9 ޲éOD]_sI 964=_oXQX=Жk϶%xWP./oVK>Gο_?s#._}uEo4<'fYHQj׽k9cJϿS.+oћO;dEN=KI`_u*5̓Wg]2GDyZw ڿtW|N\='zvۻSUgovCY4s2-o_4cM9gu.ʽݝ3/<;3ʗ5eϿ\x}_ۿ^ms6ۊʹj,W/n3|Kb$~foq y;{w'.X*g}>~]!\3:]9&S'Τ}Ze\\=H g~2m n7u:+VJ~\g;=}ƭ?7>eZw9}m5I'8";|b\ ޷M [f]q= xlODW]Y.r o^|dQ2G ]קe gp̼٪xto V +oTs8dϷW-_?H'oHۗ.N07MIPMoeR.ڸ)K}4Ou?pKYh_,xצehxCNQL^YOwYj:5)$-﹏yz8ml![ukb8e/ަভ+Yn3{uj_su}ixlC3~B@E?ANYqBo7m:ںh^[Ĝ:"s5[npg7p98`׋7g龜V~VY]뚁:mI.Ӗ+,Oܘul#ݹ?ϰ5L7B~Zl^\Oq\e +˳C'ڹy ˿bfW츧7஘%;֗BwS+T?Te?Բ@2v̆g'rlWY`|c~g =y?&λ'[ +ދxr +*s5Kt#cٲ/dž|w-Vc+rCԂŦoL_ 3&IJyGiu >yG椰+3gۼ]Vx6{]Y߮(|֙< +\'ZBťC^srNUy(ZQ/[c%P,`ǣLu̬:UZUճt^~=$?oB!,M$$;P4Mkē;^},>u̴Moľ1mZMOO>}!L"^' \{hg |~WnLFvɌ3VWSjPâjIRӭߤR05g \#lsEӗ<ßӟSRv) 3'^vmWԌ3gW= E ?$O+o1Vsn]["|4WvhnF:֪Ui+J{YϕuM32|˭. wQq޷sl7ɞ!!}bE&EJ8#絸̔J|fe>qV;]:yS..L{SpkEj;/iF-2k,'/Wbq)Ivw xaq(XR"^ۆ/G o(z!d'VؤQtAa`,d1-GM^ pnM}Ū%{Tsn=^uRSoJ<_Gc0"[Vn}y8vCз3U-VѴQ4b]޻`΁nd_sy)719ev8b;5>}zޘd#:I;&I^{+]u]A2 2 cdoU>+^zx_]1DppvO_<7&̻b +4Q{1w'Jwgt߿2ȵ[!SSaQSl}UTR@ۋo^f02Zح'2L17;~g\'[<ul~}DUo4>i!E?1x?dѼb/k 4n(+ҚU/XKhh|iOxbG7ͧo9sei0_Xdu:kVo#g-|~zBK/mzBX;s-Ҵ;Z>U=\ͻu=O=<:4խ-6s }?ldoz1#z&үJ3^zkBDn/Aӷ5YpNwoELzP0l/"Sm\TBtݲT5ϿyyMOiɻny8_{ִûvUVp~ëړ\j|LeK;Gץҝ^alգQ:C[,/]\8?+y,qwhlP򟂝;%nv;˜Gf/^ފ_wSԚ= wjL7s.?mܝC9ں#|ҝ*j?شn㵅7^#֏y;yDPJKn,b25-hyv̥VA|VsXo\P+ǘ +{s+ +{p*xW?O)hU _Z+,蓼dJ,?4޶?v C].{&^`yoE{U왫x̪#׫Ըe3׿u*.lc뙶 8kG1™wat:n˯β7{.qEÖũoK%TP¢kTL*79[+UT0='_ʖyZ* +j,NM%uZĎG7V=ڕxsM G{]p}͵/hԖ?-ZmOKb~F&'M]h"0._頾)ywp$$?8]a}oyZm%%g;gt2yJO]3xֆl%3*ag +o良g.I kn23U6E(4L|{GVM|\N,OڎG~:GY@jJ,oߺޙľi{ ~6~55e;.TwH'u12.] JR8Rt8-z``{UyR:,f[t ֫чvM><.F<<7L'ds˫豵9Tݚ2Q51'K ,k^3GB@WH:݈5ģ!3*_^kt2ӆ[)mjU#K +p"T0d7B9JNO%6l[:;U:}IKWS˝opeHf-n: sE]Ea%|Ko9,Êk+λp[=u 7W!Kwn;c}Ij_2V]kکDmdkR4/֒ q1~ؼ,KҘvb2G+}Ik֠oX[ +{yz/ ̞;]I'k)>+8nPXfĿ [ :䚯_hƝ{n[3طK?Ryǧw\n8UZ51mɜݡLl|gu\ˡ¹[nߟc{qpuyݺ.1oݳ&{Yn¾dZ9EnUcap.3xٖJAoO{yʢ(9B2(0Y]@ာĢ*TWt>eIu狎{>Lʱ]c[^J2F赾e}o43Fwv7BOk1IvwjXY8z޴E:fxIy fqNp]zۇ-LIHm*鐓5?yg}__$ox+ +NX̻@П <۴ Lzt/'Ziu7w^\dsMdӺn-^h~4[K_ {>}찷u[t|I"LRO${cZoQVn^J%y-O4lΏjƅw V5e[7O2q=ÙR>Vʤ{WٯqygP🈰7D}׼_WMn vOyQ䌸Hu"\,/y|uV}Cۉ}ƹKNnhέw1ů6ΎԻ:ᄸYp}f_3HyOxB2'_l+E oExhK~{oD"A _nֹxyOALvW%5n=msH3e+Y[#A!xmJk+mQaF":.BeYA SI[@ޭy~YnWZįd9G[@#Sޘxcew77me6=pWXk[>TRݹV*6ǰkrg\M܋:x2ʢ¼-|ay6cI.G8~9pѿql\E4H(߶OA*J IGKo?Stʿwfjnꬢ5C%on#ڜ4z+3ײks6kҩ};n٧ovYN໴bwqη:]Ms,Tv'K6$%^ -سt-[=+]Y򖾦{g#~Y8A|O0dq̳ mf,)Zg<ꪵ*<ռa7:N^g'kKՒ"E&ٵ.O=#e^8!e~B4~zgwCջzϷqs6[jZ7MzJDÏԊ9UqNeUw "^8 +wG`Zm ]ȏSDD̗nz`Ǣ_~8^oqnWIT"ՐzaٝujCU^|aۍGOS/·\O5h#_ D[gw"3C/9nQ^8}9/#2z5<立@*Fy>7v/ڳlfآzUb锻/;N?ٛvS h[2zyHR},zFs{k<2::Gs cˢ^nyp4ݖc-j}dSb"$=O滒ߞw5|㮳ÆCL}/M0> )aY_[ļSg6|iޱs;ۇEw;4/.{%Ke}`[wb$ Rs= _^uQerFW JOL6qSE30JnݾECmM7}xd$Oօ.|u7;fw5oSMtڹ<fNƿ{rLk' VW^OwNgBrkmd[ٻһS&͎}+E:߿un^slẂWD]ȍspS.m`cMHʅ3>WB'l\Qx̹׿uwuiۡ%yoҾܧ'ThS>k8SVe(@پky,{ʺfctį!i[ޫYu;CٴMlGͷt]̶`yiYJ?+x}1e3jiI8W.EtЗ%pZG<ݡ0Cy YǾxp0PNk3lx+9Kh :t.Ca'krJZf-f$mo`t@gORw*&b`QWa](qcU ++cV-!%֦r:k>։?ky_oZxR=&~_㕇nM2doN(L2Ŕy킿g=/xͬsd-^2# Kݷ>Yvd5fk 5MXdUvkW +d,w==*,_+g=\jA8ReVGoYy!BEvm/hfX]+m_ߍ3W~g/~Zn7Fu疉{~66,b ['nif|Ӆʪ,\Jj8Ӝ"?mq:xa~Uo+/?zҹ*;g} R&q4/\'tCGʜnvځr辉JkO(xpُ  {r +Ǐ2:HHYxS\/zS Fgwo/WMsǴ-p)`o[o'la6Utyl']ڍ6˯;ky{|>_DsS'znR3c`}^{N7mk#)kd@V 0 gʒ)\Gz曼~dy[ٞߋUtK%Tiy1,pɄs%50O~y)6jP0du7njuz:6)? fG~x/1JS'[ "jaڟ$tUz깃<htmx2o^5s{Brr8dD(>75gGOE4XVace +2e1!IҾگtf{/eD$;)ٯ9G~{ǫbL`X(("9 5~}W\M:cZإ?!skf\$s5򍚊Ssmf^#j &H }rB?ǻ 2)GrνrJtyG\74͸)"b%2v݉=ﭛc]=l=k#-:?[ v饏:re*<7ĞHr֣%6 34$8ƽdưw>)*Ý'Bd2HuNB]Y~-\g^8caKKn^[?2 #_ۖʊ<?i'ޓ +R7pS`9 Qݡ޳醆-[aޤ~Ug mcqvpQ97wJU=ݓdtYY8fg>-6<.rKՕ6&A+9K*h٧yk]a|G/|uk]}zo|~'d6ysmdyJR.<2(b}hXƹVp$mI.0gϭߛF_H7/g!4C4˄moutle%&,=#[}\-/U8_Q.Fſ/?{C#CS.|IJK b!+8+xi<1d?~oRk,q=s'&hd%Zt]:jWrhQѬWrgN׭6-AȠ6]gky̎ %^M[qĝ֯wo>w'KN]/~;B$y`9;97x*޹<ۅ6Mnˢ̳HS8Q꼉|.U3j{k3jo\OֳpˁQE07˺հ݈3Eu߫I64~IwmYZҲۉ44HQOk`Uӛ[Bcm"c%;~{צW7K?i~cDoILX9Lrɮ,sOzvFߚ,Ѭ{^Qo7OZϥՎڷ_o1z7kGWn4X"b|_<~/w]|ץé*uӹ |n>Q< +AVJ+b89n_*[N*_kLj^/h˄=U]\5{VR|c[kykCYNүWu˕7t6so:Y^Ks7{FI5`6ayo͞<̿?-9dU-&w/:Ea,ۀ &3'$>8lѯ^ZgOKoV0UMO٥=6\{;qLk~~66ߓgqJǝevT֊[k~LVJG~Uu>~+֣mw6-rgNog}y"}f+z$|ӻ=7r>iɵy2]PdJ1pboO3Pꫜj doϹ Mr|p:yZyy{ rperQ#o.I`PXyPbD;4:v%[b\O0qO|ȓ]s}뭧ͭ׺^r,f/68um޹tzM(?&,_$ ^z`>KmY?V_yW9Hqw\9'mJR +"+Ce.()jC-SWuL~*s1 +Ժktv9ڨx7z vXb3Ib䰌} LrVs u&wWђ{-VK"Y. LMɢS[H}RCY+{-q_ ې Y9B%,'_b+}ivqW}Q`!OΖ2SOE{mg;'/{YoyD}E<┽1%Bf{EY*NWi;55U,WJ>QWzX9iǽwɿ}QNߧǴ3۟:}Qn¦̷?m1T|~oBT,jx9>m?.BˎHW(nm +%=`}0=]Zs9~xsl?y{_jHm]qؔ~le3 +|X潐0ks+߇VD?TQ+s N *$]PCEO d^ɜM۬d6Yq_܍W}ߘV5ꞵθ^5^]整$ äFLbixn־|}q[ا[܍xpKmpeѳ?u]di}18̇*+l',=j%<κo:ΧvMygOg7jFX߲b὆)mJ{#`ٰeTSv_ JEYy msCoٽyW >xb^lof9\˅oSYYsy&=A쑍ݽW|%%n)Y?5E|g57.ųkieaGd5Hbu');:r+Yy5Z"~$LA`N C7?_5uvOwD,J8 _ +CIZĘo?04=c7M!w7-cfҝd_;g~!e _evҹ5{ +ْY(w}s)yZ9|lk+8scm/Sb_>4t}s?T/J0 xD6~,%ts9kV^Ǻ+=N~֏f.;(d?>slys/^7AO5h^yR cMAIGNNMJݻ CI\]n#3+ 7zZ\UTa7~|^/od=~۟^ 3v%0d6QKJKOf-pKaۛe[q\'m\V8~-9ܯ#gf,gyg3slZtAZ6墔B?YVO)I[{m'M,x. cqfyU~*'6l'9=nɂuA JsПISed29mx6x:>wi))g/֮02Ę +Y,zdajQ߳z^.`^Ņ\Ӷ<38vQ7{-8W+]MܭfpBd}j2?65UrfNfˁks;n۸6yϓ^[Vi~٧pnJﴟieF>~-:\*\;~l VNRݵ!Y'~'esˬٿxg6ߢ7_\|QssFmҙKˤ1zwGk~d2vzB$-t LzmJkWgpY#VYso5S_we +>K7;]ozh_rlO .p2iԪ_?Xi¯ue! +#~hO_?˷nHFmJ!)ǻ{Δp\Kt$w r?[9{Nl.D3-zPU*5_{^ɥAnmm.No QP%Ÿo͍701]4~8y憓Onzi3qz{;~m:Wn / +k'hhVUNWUX^=sY??>4^tc= +g~GQGz7ST,vؒ&?`7N8i\_yԢ{e<3w8҃;bkNnLnIb8홆w/X=tX^^W61՜HsS5_g;s~PZ$gﲺ*+gj[hza}UrUVX-HzRUG2N޸.sO#[l3k٭y~˲'^f7&Rԕ]W<֯8}_omU=w;}cʵC74'=>8,ìi6\8ub__UrvY1 zɭT|aguMO{)$ҢNQˋ8-0kF؎No=4?z(XOOϮ ;wj}Z~!aӀ5dSc,?V_Т#Op[fə'gF[@wq\.|˳>rZH=۷TEܿh2p̿fy9F7OGǷ-p+οvCך$}T׿]^qGMJ~.3V»ՎwO9WeA޴7n08m٩ev?([sGw[mcH1+rukf}_H_g^_vH_['w: +Q*vƬ鬑?6_+! .x* xM_'(|MΕcɏ{ٛxmFNB~jCWKv+W:E&dͬ +,Rޡ5mvsɓ#rY^j 9$}塠'I`}T4T>_fؖ 4r'&_ + ;K]:u x^MPFLQZ2ɭYͨ^&׺Ĥ˂+~5?:-TUf[m6޽%?.r4W~OMἐۛ>49kqݺT)|]?|Os܏.N)L;̿^he"U369IL^)jY6~,ϴf7xZ8dm,a2s5O+ojj~ gѕ3v~ib)Ӻ<-'6yU)S? k˧ruFfOI>'N띞nBgc򭝅:W7w=6QYf)K}*RD+Gj$*yZSpV~ ~g^.6 +xfE@Ok9moʟ^4m_=K_EE4a'2ОcmQUܴ翊wԥw.e߭yxqkWEKt?nilP[ʖ{<+>7>,&ט5Fn.Y(*Y:mplUr|^ +g;޸y,\Yunig&yoFc]Am^uxV۞Yf&G~ꆝ<|Y'%/߾kGVWuOĦOYbq|P8\u?ߥ7 +ovmʿT;^kxl'5O{W}_g9O'n8:z{ig ?PQ `L'nb5,uCCֹ,>q~6G^7Jӯ-> LKy`փu 'u~q|63?p9@ǻcN}8§~*ըO`e.ř͗tnplܻsʍ}z |׽ȫk#|ݦPgSY3ו?]Q'0`óoGw+fh%]敌~w`+~:_UYMYV/88RhJe>/-]ج)?%<W> O͖wv;4lĸͭ% = x/n3W~Z!OVW9ܲ/n˂-{|/K+YO=:5v΃'-ȶġ_8/צ~:O/ޞ(>Z.Tͬ;W8eŰ"ĺcp Ox>{jO?晞{\zwM7oJCʆ.4g.2猹ק.q?VoLS\?P+-IQ?Niu4r&}b먴{jvr[}x.ymv)]v[fӮFޅ7?dVϵe/qWt&ei8g_CC3X̕K択)-~t=e<ҺF|ْ U {7y#4﬉v}[=9=*I +U6cN]DOu=Tx̮R#˽I\xMPmAi'g0!W򈐪7V &n?~_g֌5"K%NndĪrO?wawO'OO׽A_-[WW-Pjwfys?l\?cܻ--]s {E MQi^w[֟~f@L+m9dڈ='ssM +qp~{6K=ÒNL%LSJg/ZT:/yZe\RnS҇uǂVwOZnfϝnohI7Μ>'U@VR}|RVGM0#/GB>?mzowCcy +Nڢ sN15H6@q”ug>zE@!]qO4.l yiOέYG?z)EcHmZgfˎAf_NLuYe]ΞTū]KGxқױOV/K>-^-9a˧3W0M7}vzDgM~0o~-d!qתf[y-[a򋂝+v=hrc[ٟ߸d˷;_y!K6sG?3g}R7IdlwyL* [dkM)T~h,;J>;)IS-`Uvϋљغo+ +7uc+Cb悐Gkgŧ.Ž_27蘔Rp`Wˬ^8wSG=:pv^ ?';^fsX/εr^ņ<g뛷㰸Oܰo6}IJOc̩[/~p's,@dѵwG+֧0a|z6ì#:ҟwhvQlm[Nhlmj35bteI[c}#!3Eymn~0Ksܜi}~?VCLO<5;;5@Fnl%_y%c>Kvͽkttz >fYpt/;Oa/y3]/xyo +eaw筶ܨcښY\H&"Ka-~Lsl߫'͎}QgF\g؞dubyJl$媾Vxֻ8Los늧3oZf_ߺQ5:*S"~_!߱M|Έ}, {u6M_;c;wp7󍧊FӚą9295͏'3V2zRS}m?/WK䈟xA9C=d/'mWqΩX`!7eՖ)_6xXj騝oeKu TzX)ɀs˲9ݸmX%'\TK4ex-8i?_Ώ6>GD-k)v.w;ѿSDOYS\箭lyV']X̥cF݆!Y콑3:^gu&U;,{| _[x e敹0?h52zdKho❌%ٞ>kB}qWB;kOl>JK/S74NouT?俪5C7,d-fƀ'ߟX+f6ژF$|ƅg^)7;g|v~Ub=ϪMwX5ޜLoz_6t9BVO뱋iFLSڏsYu~1}͓9Uiy%'W\2)AZwX7em +#lٽ7*mn<^ڻS[Qkd<':Ysw3Dyo΁f"o@7儰ɻwzpɽi&{ߙ> tKwzfyrnJ/ܾ,_O:>WrUmOO.SnTrZM;f8KRk/O3g˖|ľDR1](ڳ4fn{p!P-2>XoZ"ҝbةuB?ݯ)eÁ;^?aʲ [nlk[ȧ:b8n׼M"Zm[o^lylKO0y6ʜQU}Aܛ+-|Y/z:oA1[S9y=|Aͷv69qMS {c:ӟ_ +`z`^V5pa(ׅb3nv_;l*7KW?qq-4^c-I=+K^j;PJW_=<]fwkv +3信HtE[J.L\}w5GuNܶ7˻?!qK64o3m`ӛ;VscSot|َ9?iX8[:vM>>;{O>PǻzƳe] Ӹnr}ꁣS͛oF|:җ炟?409Y{ŁJ/ry;fs[nai9>o`SiܳGEsTEZ2-_e{ud`uL.F`AbFo(wrw􀸜eBo%DWUWNQZz|޲3OmpyZqӟ+;D5n(Py`e ƫ*S]V0>MHEk|?ԽI>^rCxq7O4{"W⅋9?4O:)ƌKm͘Q96ZLzLƦiU_d|7H J11;ꜳKs&ѡj7l_lӇmUNo=|o ]cʅu>y]|Q&VzؾT_.IXU rrpN{LEB rLoIZzߙ/mꝙ,/.MX'4Qk-I3\h6fHƮEݿy|^㍛-~ճ~8%]`%ㅩX_mo[k}u+enzVQ:KEw':][""Fͥ-[tۙYVOȲmzVD+cKX31IEdOl]^;g婾yʵmY?T/eQYxh.O;6ŏ>pa1dW}j~ׯ;;Mٜ3,VkۓXV.){Wۘmfo!>>N3{#'5m5+V-β_wGۥq,0;.{;?;F/ho=O?mivt;fZ6 ;v̴G&^}}3窙߂ ~sP]9ɳ! +-sՍ[5OK[(Qa[Os<,:~I)ѐ\vD=x^+_,x0l}d35=YUҷiI=Vms[D7kk`>aQ7EErf?p]C}ijɳ3xV)c˱e–֜f9~`nvrld哲T +}Z|vDt:ui,x$\};۫.)owg_Z۹ +;ԋsy33Vp1w׾0vz蜰! 'rK^Y혮?]U>&g̴\oe6oißSxil]Z:eDwڰglZ-Ybx^m3ٓv8ؒgGZUǡ3m piܑT=yNtx@CɟOQ-3M~-j{\lw1A6sdz}Q{bE"b~<~s/-Ա^Ŷ1m~5KvW7;xow숕k4i +h-?+hŖkS?|~-|Nlzy)s鮗sc{TYy)M^Ƞ̹GՉKW9Z;7x0q̸Jws. .4eC9Eoy4"QzwM+SN=P@ii6cwTJfc|QiCMftޱLq[_>? W?U</?PE»N/SeW7<펂gL}=R-*"=.m#8WewB7;چFOu>mn_qaF^49sa&\V/<.UyvLȑnk)_r_-ѢŻTк9܍6deQLUQnӇ5zFÍT]=ٶi:_Q(7mѢ S}Κp^"uQLf+X_:s OS_n_bl.4[ՋQ[ޞvYԛts/KeO]LF i|*=K|<ntlE#1Oۗo>,aɢ6ZܿO3(3_g~*Gmg [(ϔ,]jXĿby5)V؟P*s{X36;-}6y·4mO:u_p}8|N=}2o֦ޚPalADzow^z;9HeGۆkWz3ɏ_2^?)Ӷa%gGGX4MqlgwyTW7Lk}+hb뤇O^댗_淊I߱Li#@r2 3ӌI^:iB[ j+c\4OIϟ))lm~׵Я//~gDw:ik=Kփ5|>Y?=^_s⤠mkO +Z\pޙlt]OWT2j RчÔR%RL +83{, g-ug;K2D̟yF n >@eUʇ;'r 3㪃;/U4p z_dGF33-W[X䵕|}jMu*Wn~# 3n:3~xnoz\_$izeܫx/mօqZ~42j=N:iVrqOSg=tעE: V~ei~{OzzBWuy{i25^IZm?|zЉ^gSɼY*,tos2ę*koO9Sv"xVi펲'g~[SWJSlYܮs^_\_C&o]8~s6[[%9"qN'wT'dnJ y45+lN0ΐ[b֭%k=aU.yNeyOYN0隻ɔ-s}ϮGgBξQꚺMxͱ<5=OxPQW0%͆nU۽|cla|#N+Ɉ9{=I˸Yd&m\owM=,.pyǽ֫1aڬ>((|i+U)/LP-}^"I|Q>YE7"};{rc%KK..}G6Uɜ;Ǫ[Y⏕ϬSb.y?XS^Hи}T:gFrqϒ[W}hy?fLHYp~hoú_E>՜)Ѫ/mU+YƱVq//NnV^|AOdkMK uZ%xhty+X6;Sǀ";^|-'ߵN'jk㉋<fhY=3e|Omqag1cCVrܳ&w1]$&J^puuŌG%d^8Uҟ-mxzTs##n6g}%zǭ\ <6;wW^$?T]c}<.:NK*.3>0Slq?-VI7Fq[(^tֽKcjsv2| uO؆cw5Wo鳖t.]ܢgiĊ'E;e:$TIߔ/6q+'65-"AbEėߗyt`zqSυ<ř]sni.|M?5sOZ[(RjmK,Z`,0{ )-9Q5'JB+[p[$vwZI4*4c}psSkQ\ǑkV晞Yl93VWd*o}T{{&M8_mWԼY+OYwOnؚvB_Ya&;:y3U2¿>5o3ʮ_:ymC. +Nlj3[{Ɵ]le3Cil/dsQan@Y \-lKEu%%dY ڋYS-ޝ[X5gɞdIUϋSzvjZjڥ6\X8~TCnM=6t\Q OyWN*jo1\#uendZPcG؄mFk r/sǵNbv^90W >-SeC.ɞ=9o -<+W*v¤}s+*~l39⭒ 7 +ϙuS#Z$n!} FW(xѳADSqկ?gU4mi֭ 6+4m[ITiC̡+:vZ#}G}o$c/K#X#oG7U,Tj{Wbj.]>j~rtcwřf>|[#%6?N\.p:=XkGs_zyE=嗏ޫ&#mؙ{#Aew b#f/2_q=* M?\!ķ`tA-GqgVF]kۤ]<8K!W͔7,}SqivjŜ*v:lJN>QL]V?({?Z$f]ʽ0NyK<]qWs{KIzOwL/Uowu?$X9haª-a1-d5|e.h|ݒ#Yns*^_VyCk^l]z*ƻF !;J.8Zs-Dp+\ʪLҖM]:a +}FOLx՝>˟~h}ɂ Lش|51Sv_@g{-G׺<[f8/H9wi}Zs}+7g¦=,oj #)wŒ9-5y.q.O%or_63y|Ά eCJ̩+TzƱwWר_w+mюb>EZ}j_LJ"dgi?=}wԼ}iE6`}O`MKmޘ-ۭq˙{RݯoffƵPosWrݑ=9ǣBȇ/Mp똞ys`EF]iGg:ͼua]zv-FiuA_:{د2{n}2|wڛ%O۬s`/#n_~ۗ|Wa8f4sO?:UC;-]7hiT:?%!J*j7^.\T^8}*g\wkc 42Gg|??Qx^K?]ا?vBF5?of|kvkr֙1xBw\ծ{L8qfBE,Vv';Ғ,Nݗbsg?niv\eW=X'8 *\S5e%w\pʱ;lFg#$zyqn{'Q}.x6R[nӂrUm}EGEr?LFs.9KzKLunVTtYz_?omǻ}bLo)Ku<낹f 2{vy۰G. ʥZbX6U_J]ystI.IGInB;s,dDTic;>r\<;ʽWj۴B{* M_h]n\7!n=[g*/Xi>7e\}q~'r-2 8C|Oy|_OXWXbhGhۦi֐WZrɥ?ݫMZGl-_q8#IA`z UMۻf;79EůY|~S?jx2Iś3o}l`\yD) x荘1i.>%ٽBs^n{{]`Ϝԩ=YR.u'km("sǭiac3A?9Ny*bY|;f +\~r<&oa;)B˥^lwɖ^R(¡'8a +\5?;UBʯmLl,5;8v)U/Hb]:6N'ytN~Ts%w)bn+ .;!m1Y4Ly;3S^Gھf3'zΐ{o|ϗ?߽X&4<6F,Sk==򏫟-!LӵWaח/[O:"o~ikEY9K߿Y"s}ONh< ź?Q}1/,f%Wd|ōp'?ݴ~ӄgN"+ak"aXۙÖ?bT~|kS:Oc'9>xCʉC%-YGn혵f l;ΘHNeʣYO>zO[׻!2~O]Qj!Fr!}&+%~%ȩ-%XzռtՋVnYi=ꑣ}ln5N(mZ:^͖ gמ0y0D/]Yvh~PzRB1N o6hYy=:*UyTud~6ztф[mw[~1w@!Z+rU}EG+Yvmwէ=wqi7.GǾqRUPS.V4kd0T12yN3o UTfߗq`զï20.V#i,cV7iZ*6c$5Nh\?Ĝ`[57=}_3ǗdV%Esk~,=zypY=TwzjӟiN4!&'?kMz$QiR˄9Jo50K\QeYa +;t ,P[%nb +-_~$Uzl˶=[7(cz{̙>'d~tZV{qw9 S vL{_ +=Ro-6uZ@7,gKl[s +cɠW%l(~(.Mw*>gW?j ;{ԅf?:~ztS䉦+R_t7w.ܵEtΙx?lv< JlՍFI4ͿT& ?*Y +zܾwJLW8^H5J +>3n'׋hkd^^q&':kՋb[k^]+˦`]_̵ݜXp;gGl*SVyi?Nd$B_ݖ钷^?Tmզ'nMZZSN>=_~I)Q{+*3^ٶ%w:7]jDkۻY@B{,/>X,،z'ۼjsMjJENrf +%*bSemD~饬%m)`ŔdVnTT؟}!ܔkâ)z׼r_nRcrn[!cuc}{Μǂ'7=s\{Q+yV67>U\v]Δ/=76{rQ{Ǖۂ9ufIܼxL?▿M8I]#|~KSen:f{֙L~fuc}ꩦ܏+n~yOI$CK>*헶vxf=?u3ngrU5)hJe>33qiUosfM0mte|q]N,|VoCjT.{\pW/O2* bcxjA *EU8{QL;7,縓WՆm&9OҶ ٫*Bo{W~u՜;}*㢹'GSC_/UZvGsxgv%1%IDOjι|N;[s,Děe'>:Dڭ!, +&&=R` ք앁s;(,#Uw$ )"BXdgJ4PzϥW֩s>B[?v|~Xgc'Wf96g5Sf,|g2'[n*}ݦ%[]#GFW3~I;?p~altov)oRjo_xU:wONL)}нm?ϸu{4o#NXj]םi)Ul/{>Ϧp(km[S2ɒ*WۛvŸɹeכߓ²S|?y *'r][r=1HKXo!`v4+1o0ǵU\\410$/>nҷ-,fk=uRy3*s?/R5gO+[אu֍W/< +fi*7N/.4̈́Yo6jV `(P#T%Z @jgFil[>[h"3 ]}[ 6yeo~zWj]+>@iOw~WLoADDL^?!Ɲo݉cw)O/w=g3 <'ϊPHRf~\?:/֗jNjXoŴ ,md7헔?}x9ȴ3bߥ3J3x!^߰.xr_wQ>KoHmUUe'-lɻ6pgJnq蕆Yw.بwwWBfpkg5S +Wؼy͕{7;tB7ǘnY.8-bCS? ywKJ]D-^?K3ě/i`QoWhZG\mvڱTqF${󪩋M|u ALLWgko?ukD[.Q 3){Y^;3I4_dsSʼ ))L>izNb}džcb-[=׬~~xn;,:q,ޯZ˗+r+;Ns86qWzoj?WGleSkS#V9K-quUVy嬟|b&UΎ]/~+hLO:Ls+1%}k{-َ٧d}^\~K|uX y{END]j~t:Y/*tjr{ϧgǿ/D:6꽒tDkE |r׉n >]$eB{/Jخ\(qqkGȟX()ۺ#f{cH]9v=jIk_ ._do"۞ߣݭcqcwDxѝYQgDEk7mZ#B2DZ=>_}߄/$ZJy0<~a}HKLL[ZeD,;U,?h4NKvxXr\c.SOș\z:ۼۛ)XV<䒰ENWzo4sc{3 :v[vFѳU anrZ2O=oe\&>sֺku]W ,F~< +?K%3t~+g3Ͳ6Q8u3uw;ہg<,IrSdkxɼڹ;)*mc<ʾGo_{XoOw 7hgm+%8ǸX24NkM7G; o x}Z`s30/{Yܴջ"+cc(17#&T~֠)~m.];?cJ'NɈ1ѬгOj-sR {>Qs}y˵,\{~|VKkd HE˺%}Jw{cX^ycw Sf7oKY7dQ*wyV"\Zgݩ{l +x_hw:JG/Ε_ٰtwbM=Ĉi鏷Ɵ{63'gm77͔ +Tk],?Cُ_1ehwi["uDZ9lomnTſق9mK?BьS_K9nlu+Yid?q:)iHDٚط{4nέcx[R+V -y&>+vt.\`r(}xkYBA*i_>z:X@GAu ʯv65vAѡk Q{9/\Lm2}_UwAÇvk\l'-ߵoylnBeӤ>Lc(oPpHK[՝d>RvO|q6\ᵄeS q8%l٩v{rqq\Cf'HoYvQ5^Ro5?]jQ@BMm(՘gGݜ0k^֦]}=;ž[[vܤ'G=ǭ0,7xCOWSu3YvM'*6D3S\<]}*B,C,WB^;[k~Nb7\Y{7)VK^,*nyRƕ~†w/'2/!9hKpP~x织2הPvo-_~ _rb;iu׌<ٻٷ곂?X ^Ĵ512xY}asSw<|wG,bmOPlS '?ϟ}wZLk=֢ѯbN=\h?몯EEb,92N^0iZɳTGK-kVoI~ߔ:|]o:Lxsr9}nc[HC틈7e~>]#ypKяA,k{־R_UeWx+>lQ~jr_f<Ro*WAWW>(Lص0 afc}Z8X΃1}8?.0Һk{Vz'{ /k..w]e]6w`̟v)ȕTv鱵?0kyXŴL]Nyx̐\ވӋ'α]Su)׬ޗ{l'(x8STC|i=/7YΞ3Vgl(yg#4QuBkDйK׎8l] ϹBtE}gY\~XK-\2A=tj,b?;h|"-A־3K\xx]]={aGOz/['\9od2 Aϖ5||Ub + cM,/nܭ;ɺ]Ӆu^N?*bsrU5k6[gyijOYQtSX5o|ZX۹2=+ݧ/{f\Nb2GW3]O>)P5w89|{|&[+䲈|t(|)/;~̃7OX*˪֮r]+MbUW׬)b?T7xcvu}ovL%ɗ+K]lDQUZq@Nџ%}5Z&U=ڣ&IKm4v׵zeyi^,=e3nQl LE펞+o -XF˗='].hBW./vjWsnepfu\y7: ơ}JOlG{%sY'i~&[b/9'?b뿕Qt~yX)W1-11ۺWW:ԥϬ#>0]Fb#zf2Nݓ4/1:.`c|K0~UgsXoӋ<r#[OW[w3ݑn5K(3Uu-gfQ]+Mo&%>_[q`M +LE25wm\9"y g崜;>~]]e&]quILQң>k^ytv I;?'u+ym qY527Z1Y}YN7|gi5 \ݫOJz'-f89K_ŗ` +تEUӳf(.*%`P.iu7ojlޫxmv%_#XĹpo/kCFjF2J[靌+TxO~_ŃnJk%(U#s`e6ç[u=%$x6/]o`0d[o_G +E%ýe+H%݉A{ K#^R>t4rخY'Ϟr?;%{(zkv/WzsJop{/T2Eڭ?[rz9iC5 =[eYs~hϻJk`ؙjtHcg,Y<ϰe><"]*Q/W_{.e'l ;^Y|ioIW%Er;.x:傤D37?;n Y]i4U5+UD=4dvlj6m"&]//O?gbkç>aKˋG#ބ_5pWpY: +ŗ'Nx~*IQ5.hs$?'$;8$m7 {4zşf_6(:1AI ۷d$̸nVA; 5+u*]/Gc[ju3y]`|ѕ{j2NH|yk&|T5ڮ:2M{ľ"ss75 8&~dn Dv9WN[xr0U]hAũ\XPnys|Ǯ]cՎo2Y£'JhXYp譓>$?|صu8-0g&I =i8gq# 8 VNq1}9iaU#aw8'u/*zhE0|J2+/Y/ !*FJ+mKgJV=W\]Lv^ۮ;.s&r=+jy6sh/bjΎޣ{犞M?yf}_e%K:\:MO$D* rK'%n1$B]OpalXvqrBg2K +L1Sʹ LPֹC|iؓo/rm^;\0{6%T' /3bw}Z`Pdf}olUt}t(ZCW#K\U9_S۹Gv\[j2GJ+ .h\Tx8C>rrdd^XZkyŦ .Rt^Z>^|k9pNSo|$QydW؊w8߽$ǮqZW'7 }TZ<޸ߝqrwO>S&"fmke{٬ܐ++o$PZYB_)f6ƽ,_ +pMǓv/`YRk ˓W>ETw{v-ϊq|彤t%l{K~_]q6ʼno3Ԭ0~I9OӥuR7 js\WMq+軂MkKG]6ٺsv +}nu;knK,ڋ$ԹʩޖJnpd@_,'4+t3׫iDz nZˮ鍡Xo8HW~d〲M &C>Z158MՍ e֩}"/b;r0>o,s"[]Nys񉋨,BºJ}g7qJU71M`MZ=esB%,U[O6|pYx=iQhwgmlۇ"y<NN\)i+/%fղ[eoFGgB7/2j8n~yi64} a<$Y.{}{agyˍWP;9XDyu#Â]?_Q(\' +ۢ|BMeg_g+Jai/ܱϓ _WqZ֣yRBE巭nPܴXX\qКҩK[\B;wmtXjkSTUBEX36{[Rr:噧`2sSI)ctN=WJg#׍V+ꯒg7x$<$$D? ܡYG7fWmY{W+}$g>Ȼ|3+~gooL#~ +i8`XR֝5 Ziq N8"9*![]#hUI_&ZĻRMܷrߋ,*]m>)\SF@Kj@KvQ|eV쫆^敲jo&wb CCs,T&lxCպrQ+RX!y%^ 7eSv|vzrĞOVd-=ng`PH?UW.$4k9?Y~ؠ:2_мXtkRDy+d\ę7'lɚXKk=6VvbK[)nW!{yS&#^)'4\wGBoTv NYlXwf+rGC/ٻ1p7Ƌ0{ΈSe:U[dʹ*꽖(LZy?W63Mb.n2k (a7/#"=^ջ.l'vMV9)Z|nou} 'OʉbkK"}RÇ[|?pzeMmA|♸l⮢n30Oȡn}ɶ7Mi>{]%^l~̾sI*s|Z*Y7& +~ ^UYؙ.?+y+.Ulk̙ߋ`UQ<C]QZobeut':%oշ[Uf&|󣯖'ľ^ Q+w{OqgO.~.wzYI"q/uQrzȩ}_%kO:8c¦USLfoξFǝI}(!qofmwԨ?M[~aqۜOjJFʎY;W['4nQ}>Q]l|:;>`6rN=.LO =Z$;uȇ? 6hr^[e홦ĉvx򦽡9n_kM?piKW\}:N-Xy+ ~]V?֞u/Zt~4=G: ;}##7ßRLyTbj[8}Zql!L!ElY^}*Ǻ2[yf왨ZxbmN;F /[džcy>=fz*.IZ/h{.sjO%߾sr_,;/NOH~['y?/9Է,uWt;|+fW'Z>}Hҍ>֥b?cu#>-ad/oNϬʜ=MY] [vo7O|}S]JpwbSD-Ex||C99ĩJoc%eÂRiUK%^\Ca881Ft~3nx[C +a~zxΝ[mPb0)ڶTj Y ZUUv݌X)Qi>ߏgSìlftZjQ.[#udOnj*0N=}QtF;rѺI-:sBx~0{4zEށ)k6kw`]}+3=o}~G˻9'3+~`:d~1]^)+$.٥;s._R})Xf,żb%/Z~P>z9މ;glpb?8gڜo]{'Z}iySȚo"כP>WWd<6g>{*W&@71?JLgȝ)hpvq< Q3l ~ӹ_ o1yK+eS^5 ޱ|sgMŸ^` u'2X2o?ʹ{SuճN;-zܳAW=Շrs3fiO +9AڕV}H˞RqlmVϱz?06`b,"2{ss,rfWdSx4{3q/8u^I= [sZHݥUr|a=all}56{;JX_}Qg +qx$fσYFu#io(wM5Wf=z)ǼQ8l־p_Wğ]`)So~]7dߜa_r 56/JI)\#fgO5#8ۡ +֬}yUb? P(CjNZVeXḍيO+UH*\iZwg0}~lST/XYXyv檷'f=ؠ^kWQ5{9mgO>_'li<~xngϞMҹEYl+OL}3.=\i]˶#GVw[)p؃Ԑ"=S]\s}Ѫꯋg":RI'ZTpPJDK'֪`{|.掇7Y[T]νN[6)]pyp3>\H`k[~1q1;7'D,YsgBF =2sٽšL8 +Û[!΃gk'_6@(9gWyk]{qGw2KM[fYtp3~cS9CX4}_IK6?=wO;߾cʄs#Ϟ )g-'OydӳR~8[{F1N+Nid^Wi?A6{e&T1۠J1cZG#{ s2䪽/oAʚZ&ĉMteKGa8(fvI-[?uNr uvm<%] +_-:)&J껈|/#&@_>fQVɿ ~uOWv߇sNm/9pQO_e0/[]ldsc%B^?F,|qO>=t6^5統}aO#Ws;&z֭luqR-_K{ɔ{a 6wL]bYHy왺/5\q֡F=yjZsEUO|tttfJnRu㎧tKe{6,/tvpC!#%{kw4۶%;iK~J%fSN+3" (u5;=>S+3[wHKtlzЙ/.(_jz@߬|Xpɮld{eC|soWB.7.5\)Pս [fm4}q]q'3n<|6F?'M?8/q9٭.A:}M{c7i /?dV5ƣެN\j^Y&Io۲z_?׻Y"^(|׭׳n?]ػM̌|v&/~2s۪G,#1rmf^MJGȪu)7.Q';%K9u#a[˞Ƥ5ݝsJfƵS?=;lk7jac&껻z%QXW;tީzq3qޡү-NntڹWzmThkmXVDt9dt2ϳw혂L/OhmΌ'&T~4se?EWWst8骸sɧsy.yF2kLYxΎRr>k松'L֮lZ{>EnE);_.0鏾=w[xQ|3/UJ0x.v]J/fBMu,/~,:sn׻Tfo,ugc82>vwW/۞a=zu?~rRau_cf ':>g5VA_-ǮN4K.,95s\ +rd'$/]u?=ô3Vc/Nê7,OS(}EvӪ9눘 +}IlF׾&gOiR0zssaD#euh{qfsVp>_3.\OEgg5u ˗y8ni|쮜<ٕ¿9>J}겥js+mݙ^fT}&gB)e +w3YP({jxb\;^8n z'-b*]-ze_9Z^}Kmn +[>"E-o\Q$]*͡%Nl⨊Z$/޲#L8d5gDuU;_){G퓦t;}]w!=M>ܵ9ΦjyڡL- [6x9z;4qϒSY;!/> _ ms{wCj!+v޲Qc}xCt*_GgZNvMs"{^I}yZi)rq]*t&.Xb_[dikthL|_`o;]KG?N7'Sk_/?Δ|sֿߜX_0qڇζ΢ +]ΧN\E`%ymV~kBKg*Yj/>1Rf߬'Z|3eűnuX:Qbf-:em<=Dbފ%"ŏߡzѳ+%026;9D$ekyF\Ӥgڷ.߫/\% ,q OמT?n/pCQN9S z$Cpovִ~w"×zY??_Isݓnl昴}K{+}<=9.‰ٵ{48/zdrIeϞRnWԎOv>Ao#u={[IgB %ftzI&?9r#ߢYOIh +uڮR3)DGpnuWxZeqRnD^ 7ͶȊp?z*e~Ycԏ=ODﱌ=2K[-|/9o5ޚkzsTeV?vVTd:dۊ1;Wu]휜]ϼQ}Z1Y`<v|ݏxҽZ(2GnZoSo ?tأLfXH>Mm_okϬU^63xc/1fq~(ܤ_~T~_yמx 2ml§ݯ Zk[yR._=鑇AɈYyN=#9oΒ+.Yga.W+tᳰi{k/)|?Ks#Tq*W\V9K%'~i3m!Q)w'}~ܓE4}]v\Vym)ySwň'E6!iJaSXT媬u:=]L^}!aYQ8Jo _}3L>V]&ˮ_k_zμ>vvܲ75;1ۙV^ug?Ja'+>蝹OMY9`?gkWw{gm p>x~Аٯ}޳eu(]LWT ^poŎmx #U^5׈-h.gR:?Ek=Wg{xhRޥł_,}aKL;Nю>kb"V\N,#{wNnpևvWY[rWр庨s_;p2@b־ dY7dVĢ =G|-)c?˕nI7D6E;yoV G枢5R7G%L-mX_إ!zStg;ytwTIۿS52;˴ֶDխrܱsΌs>NWEK\~`cm٬YޏϞ;{jq2ӗo{8[HN(~.W'o_i86 '2>zUVf>tv|rf\j bO7 }{|4)\j,1Qvzp-[}r:do! +?]%zJ~@lsMϩg}E'CҬһ9 =?9p„6K&Iߞ Wy[vlf1eΏgRrά)ٻ]wm:XvMݶjKq&n}Vbk7z]˝nE0>wqɪݼ֔h8UčrZzˮs[5xƵ4ke?sL|tBrgA^O5h=U\tz;Sneƍӕڙ^sntK>ߟ>P +!ϔSW^w]/= 6=n`q҈QRS}7p?p)֝g-\4Kj 0!}uՖu7-La 5wvqf}ZgfΧVԭJ__b7:%F1ֱ;0sa`8Ib-O3-.1dnW_5YCvRR*PttE}gͪDMw:¾4N`fYo@ tZt_:SbŚ.k' 5m}ld.Pg-쉟|}o/s.yasjOXų8Ԛ[~9kk$M[Va}98ix!:k{oy~bOY֎nMSY5r`k=.:'_dV_r%so3x65i/sϷw.qXL!fffxp B-4ן(rxDqעr9'.4~^Ing6!Tg!(g{zC~LJO, +=ug%?nUXGΠur"ܒsl|T:r[|ǻGd6YoF̱ڂ(pA9Go8^Ҽ6p|z&_9{ gw8;rGUUS s5;X5պo74qϽ +Xw-^KɻlI;}h.wkEt-hǿė_R~|r`,핇),Lhǹpb^zrۦze'{<"fSt|f'=r5 ɛZw7Q~T2E O'.|Ix gx@eq~3z=\]q?;_~9uiuӇE+/Yz5#L=nt;>\ϥ1klDOUfe\:Y!~tRs}r[ 3M_Fm(t$^]ؠ8V0kWOxTSsC^ nzNS릻'/73ܷj'Ӯ-y͗Wly9{zi/zګYI63sZ׍6_`j~W1'Xk9h)O G}TCf{؏^zӂmo=UyuBr]=SWq/A[skR:e.?蹵;xbkEeYV|Tݻz&@g=Ұe޹p ^U5ܵ'/+OGs_1crü[P%()bGyo,`TgQ\WҢ6uzʥ +}zbc+X]$yrۗwK/ޜI1v~tѹd +O|:i~FݚÔYX!`sƭ{)ʭ*{nGlx:Pk_>M|Q g_.oдyz`xfWgyƜ\8y&0+kd45_w|i|q]dJS.巻P- 6Q9s?սm.}E74ޓsۧ]s\$>S?g2幻8k5KN ݕ#VcvBO-8~[b'bBXWQ^DzJg[tk#,NlaRnZm3qU-.fyZov '%M<}Q +%k'}|{qTyj+&6ry07DC.X]Acs|[bwoT#'$imynwUW3<`4"UgKS'窵޸Jďi6*oNY~e?X/z2 s:m_LS^ gF|woׇV+й|/RR^QuFW^je.-VGƩ4hg`{ߤA&A/忝~m,yҧN;n>9ZcVWZr -`fqG"G6Vxd_MGe;ޢ7D@)/'ĥ.9N`=kO5FY>6W^u(/tȞ +1俽_G# +[Mk >xd|Ȍ7~_sw)H޴GSބ͆J1ݚ#ltSr۟/.b]uL&b-|f\+;W2ԪgN{'S߹w߭q>5ٽ߿F6[~uһP뱿9_qfyF('j3/zEk_qVYViv;2|ѿS뿵 +v5n|޷+gɽX8@zg9mֿz\LSD'h4x|l~e%L:O_J $wKη{?nL/n׵AŁUuS} b5Ƕ</Z"ck[v~Ke3 w<*Xn}|vFn{Wɇ?=wK%svWT>1Q}[QMˌ{8wE]3:AvU= +su2kSKᮠ"akg/emo +<ᢥ8F 1[L.yʷù7-{XX rHVD?;%v+w9qo矌x7%1 +i?uEJl-d[/,{yTgVrzLD8oKt^Lx3-ތ傝Csd2*a^b}4v+^ +^'oXC@3LK=\|r/{~f$}N9}eɩ {SsbA-rkwm9¿W*[gz2f(>1ݴ,BG,JGk+3Nw2Nvwmn"cvĩקZr++w+zQ_}^->{JX8b]Nq^zE Td*H2+qEJ/nK\)d&7K'vso٭[7}{Mtn KVw(߬~!p;Hmn܍\ae*sd86*qr>o`x5ypxXiӶ/6׫Qg?q糛.62+LΐW?)ɦQ)2.͌?0Κf֣t-_)Ε[zj\i}oXͥDwͰ6)rXP|;aݩv~&f)4=Ѽԕ4MO?9=i܅76>x?(tؖxEwS?欄C]ynQo˝ts_︔srdׯ|{@id%&HTCDk]8s=SnQqFouȸ[Ŗ*ttezԟ9V ţO+Dm].) +UL\x:?z-;O:fA>&.3Aȟr,\qݼ.`/NK{AC737K]ظ)諠j7)|̋&/a~.j[q!cGO~<ֶ}Y3D~OU_wS揵&{T*VE怟׭oNFr\\|n,~ƩOCw>K_s捫Olod;/Jzx^+tn|=R̙Ė_C#pǏkoXw%7JKK~t [e9Hg~6VhJگ?!=}TuBso]z*mbǝ)nw=7jXrykr?F/.Y䟼$xe9W +)l t>w79#Ҧ?m|8׺_ 6,GcWGrg\3՜o9j:uH9(7'~V&{ԢG r ߻&s~]<﯈If_)]TWs\|b]ZyGkk༽VXQȶ`}_}py]B΃7[ONoM[AJ{u.GŤԦ\-oݱjkczҽN/,'Wzqq;UU ,ԙ6߀gዧ xվi |P &)[<ՠ|{_Ķ٩S5y屘Yܲ :qyK=uliIzoxo|Y0+״_嫿2*6|lR&ȏo׽JB +l9Z<{_l.wLP>}rRs};54JsoO7[-93jrO=+"Yf|;3լc_%9C%xJoxe<|'OL~Z}oI18mGq xҺgo}W2ͻƛ^_}זK}:rmyd-aJLq](58ᛢvtnu{ +-(,߼WAWۧ~*,0]bɅYYG1ywVrQĔ?JMrUXިgpǹ9lodjB}ӎ%O|\4b&TVޅn٬XhpH}j@*n68Q0z gĩ(^O9|;;_BȋS^~]W0&iz*cR[/ [?1&Nɷl[_Putռ\})/Mv;{Ha)oBE*_ ,W{9F*懮d鉧/.!~Gu C}?(Wt{dLtӖ2θ}4N?#H04|a+sY3XkggH4>7 +{}΅ͮ}> r NzSrHSגKJ؞Nu4^[t^LguqyWjw_w jmK~h݅^Y[#{z>eZJwɿx;&in7Qny9ɩ/iO2OwH|φ4^;.6wO̩/Xݿbߚ&nyՍqXImiM9U5-򟖍T_3KHy[V{y󩝹L.d̙/}cjfi~7]3S~N}a~֞"r8Oظ캪U7<+-$T/:#HYVm/M̐?8ܫGf ϛcыnIW7흢z?,ueĝ +E^yr`-\ +G3O2lIlffCƇ_!5lQ%G-?^="OռYrB:iKϓzװLesZa^#"ħkrV/t[ ܓ+VWڕpb'+V#)7f?\@oė}WGO?/χϋ<83?7_mfVG^*}+kA[Y>=<ɷzw64rh833Om3*ڻ^UOu~zʯ..PtvkUB, o,c<)51&<W1w^85d^ee5sZ[;ɼpeyaev!2GǦ;~RdǷWwE}znof¼7;(bIv>4îmZE[w&ojv57`}bosz/rx~tk/U?7㟾;Sv|f6A>3(rOf+m&J!\ :=z֪L:eUGo?|Zt[*jDb#>17k}y#żstY|~eE>ݥ_tQ}zɦoync؞ٙf5\ ֡x+_ /d}6oEs\\$x|IkoKzm3fo}Q + +n_V68=&h:_Koم7Nol6P:KSsƝ  .s =l޹|N`czKOK۷.o.dי}y?dۺ2JtgWSwFTS}쏺6Z'Ka +/[Tq-<'hp!B#.;}mgNQ`lXu3MmR=\WrvV&i;U }?d &tr>޷3t}zN{Z-黺W.;=^,늎 I[CewY\UgO40;Y9g9U5yp.,9V+n=Sؚ䲹?Nq/ƶ<Z鯲%뮽=a}4-;*ne7*?lpWɏ斘輚odg<~q}*C6f`g &7'L+u͇'=hnjEIJY/7gKWŽS`埶9w͓x+-av2}>-`ΉIuEVu&ieozeZ=:CE?ez`r}W&{)u~z^o߻+B&,/N2~\$i][g>_ ⶌ_껊\ɯ&MI +̱iV3vdEqߴ\{Z$ͲKTN* ŒTe]ٛx@E'f>|BņM:kC/M٘u_I80lMF~DO +_lbRF +ґSm{$#k$'ۿ&ryg۶.mnj{4-Vhޕz9wOeQ)9o69WF024hcԔ_Ay +S6s2dg)Sjݩ {4#}F[$'$znG2\]Xmg0Lɍ#Bf͔+})[lkpiyғ6V.gjo-y͈q>YGUwNZu8j DZ86I*b޾ d ԚW\I׆4W=CSƄ#ovD +Nmi]|׳TjY[En_;&N%=^v˗O[?7&NiCi2[u5 ^]%7}sE@I)q2s~鳬Ι;#ss$ޤ:`5,ymқy6m~Wۇ̬On5m;m:1eV,y#xc|:qO?榏Jcu;BDLh}5xRﲩ7 ;Uf8'꛳fnSfʻJ?4NyfG >+krlyȟg4.Pȇ?#c٬߶Z6#*>8~2s9Cn1OE~^Ō, F۲,iX9bW!W_UؽjGt?y+sĵ7'^೏sWcGʌY>CΪ+{վ]1Wy;<Q8aa4sʩ.?t"\!Qx%Z.neuFRy:Mϟ&GVgss }}Ojp+)YQI?iikn]1KY0g7o^YӰpv^)O_SQag5ojA@=8_Yݞ\pA;>}x<0RF|9U{}[wJS"B~UU w4ZP0{^;C˶9w^$|t҄Օ4.o1\٪pő@[oAz5 +y-qmkjr;4x!Gk6'ǰJkM|fyu3 ?\],EAsGkߦnSnW_w̱ZgOޗ\|}ۅ [.|+aвɆ/aa&QE񎯻3LÖз]Sy򙪳/x5q#Q5#x/ުٷ$r%W`Dv8zuT_ιs#$(ж1Ze6XϽX#ӯXD?gIO%cLw3~zjcNv;MVwsϘz/eox݆Le{IO>[@x!rugܹ&POS /~؄W{Nrԯ=d|䩋7v&0V=(3Oiޮ3sU= .o( sK ~t,Lm)zg cm+wYx/]K:)<2śTdr+B(dmݒ{`̋ nK=TvG~v[gn-gəwO*!gMnh{2+~w%n/S:;IٜeJnU~Mj~ysd?yK_>]_Ŷ^2 +>9׳EcRHyRͷsg2aŊZ&8=~AՓK's~1ۨ"|n)㝵dr>_{\݁u} O\:g\T߳q뼹p&Tx95FɳOm|ëȷmH.ɲU܇B'wQڽ>2z='%ӱ{?p]{||1]4hҬ mھm%sIuʯ6m}>0 +ʿq~R}q`՚?taVW=(3dm6q"YHִ2{"Sު?<.eߛ1L<~3 d~:a!dWB)|%m]x|QoQuD1*5SҲ( EORWjqޠhܷoFӾ_U˕֦R}{Xγ<|"#-WgOۻY?zE]l|{Jdv5~\XV=f~l?nɪi*6+?L/S+k]ibŽNVNImQ ϷH4,8XWdְ}̪UqI/T ѽǵ>fwO۪ޫsxoKf;nsRѡ[Qُ@GN)钔Ǯ V̝Zg}{ӼטsNf?phKbcqWeDKgݜ9u?{Ϗ ;2٧o.Koqj_4NAÛˎ=v%WE_]Ux/wkx >gD;gLݱ駣7M WͩiWx9gOXKP#1Tx-[+gi8.c޴ϋjZ{>ߩ^ qdhb9sIvIn_?^gzݓ.Ys}\@\!շ~-(5ٲ`o־Wt=};I̙[>4q]_d#|+/syI(UnN \.?!!t䣌lIk6휗 .>ط܎>:=Gu톍秪K狧t:5&,?ku*{lZ'+b=] |IK@j")fw1Eet9 Y]XU^"ͱ<{0:ZZYWxȹ&V=W9{KiU9vuOkYܢ'͇-&;v)~MiO:7{ǝ}y+'.*O:=W'|X]rg;N$K~fVUbu+}yh獗,="iλ3F61f'{%,?tڝ+졦K{ʜ#>SsE +B+%)JsڏBܬ>-3U(щ{if׿WFz(p+RRSs|_sDqkƱ=VN6uyrՋ.~{^N޷U5?gY}TzӦNt=?L+ycR֯dfm}YKLޏ١ &]p+ ?abevj־:|?t篠ٗ:s9q~5}TqLsœ·& :MW岜h&V)\YLm~{Bؔo-z6Ω+;Тs+^?rą{}k 6lJJkV|KT~;dչEQ'LK\]$u/G 'fs +GO*Yee?mm\_B\ N?1 +n+v%ejDągι❕{g_W>1Η=w5l;\r?Yƅm?C-o9;7=^^GRY[CF3WU6l4r8xrGT# /[Q{sl;:;85GwYqsYL4ɠ̲S]g-LQy4V`LlN_6%3JrЫ|˝7x<s &ߥv"RES:ϟ_zf۝ IZsAi;NǟXO*J'6Vs_^h›imYsnjh59QQ\ohŸWS_i͇E-n߿׵+p*ۂ.΃ OEFjLәxrh1{xMbc6k^Z sx^sכJ[i4!iyϸݰh +؏ +;jwv64u*Jؒk +YſI#_Ȓ<.uܩz$0i.Gxw}ޮ_7CX⑞bns}3Kf߭,mv${Yj35Y6ԭ9- a9!'oX?RH\E~&6|8Z,s{^O9-UM D,V8kϋls''Jt&\/Ae*;M5OE +ۼԳ,~2Z4%tYjJ0L{x.˂U8CʥZ.S|8~_uC35 U^)KDRʽ˝,9d?_~Μzv)"΢g +rD~VUor>{NJ>ބ# VU/_J䍥7S9c6+ռǧ\]iKt+6K酟{2NZ37akjPl"JAz$gDq0n W]-WmMրo T{nz=`;,-"x>!uBQ+ &,Θ[ .Jz*5["si[gݗɾw)c˝3 +~5}~gb'-7KM >. +gZOp;-ǟE0(^&pwѪͶ5Wε{?eyeA|7j?Ӌ߱ג5޾bnE>N*o#^U6LUv+.;wAd1/ }/G}xO-Rl /V?ޞ7R/fONխ#3/^ eO=Ժj#\2dyby᫟1lȖ[hBەkCRipRtMd%JkGE&+'7^]bvٷ>9i\\h߫n=ҒLw۟m'b>Cʼo2E +7lNc4a' K3m꧹ظ<BΠ~*Mfޙ qNovf2f#ƭW{V|ߴ+T~d9I' Gjׂ DΔ}9'Z[;'(Wܠ":5g:ȸ4-ƞv➹+7o\uϾK"gK~ :=Ϫ^-XxwNj5k[𳆰Ydt;Eb)D{y?'Pofcu'.ȺesZsݗwj5ڸ>8}Iz넯>kWjn_3?g?/秗"%/Fg1sLBhuu='־{可W{ 6qc˒iלMw\ /R5[봷NXn|X6gぷB2^\<'>O(9Y8yQA7R.]t9~RoѮT3 Nޣ"s;S^~X~Ndɫ_}ܑU.bozuLuU1sY՘4]{|)Wl'G]֌o˹ZBkgnX *#ΔEIg8kd<=GG݃ [:2="Ƈ ">JDw?rj_$/,jjzf<^^ypT8斛Z`g\FUimS.$(Lc鳙u ׾ɤo,yȈo_Oh'yl7IH}scb 9uv؝9kMiJ'6>l\ohʄ'N[~~mJ'L|oE-K&[qZ!|7财u5+?}}Q9I0ċ7Vly+33' ',-}f~5~0ٹ?c wΘW-vуeScTs_*ܧc\m夹^w,t H:0ʾL'=Lf[>Q!h3.PY婳GymgY޻oΟᢾm\Kf& N ;7Dž=qHڬf-ێI(}lY2y綠*L,5pJR'í7fd'=wppcr+M~G? +P"EO敉?L:*7_|WPVyղ5[`S͚s~>wcj >N?5o$/K֓U,>rK3Dʊ$sr`tƣ :Ѭ䦭-,:Wj{&>4ʨrwGwI/U~zO;klB] S$e~cG36oԍnw;قGָFf/CExU%%CW 5'"ϜM ';o-~dQ)Ɋym <1#V.FͶ<О{{uvK.m6iO5z/R>8>vaCo^Moj ە`֫}sl5 {RmFmI[E +S^ekVh'Z{yʹ'm03wJ5RNpH%ky'?n}5|ҿnA53g +k;֬Z&o_wI|i\Ooj/m"S[\N_e+_w( 3`X=pƯW\XZMҳwFE[XG ӎrp#b=BQ_v~]w/noo{%O Y+krk'|^Kwc:CUe}ot(+lts5jVvy72G*a{Ty|෕1lw]kz<60A;Xr6㬏f[˷vYНۨF&c>UEoWEzkR# e׽53 l+,ɨmzΝx{+݆Kpν,lopR3sk# TO(Ց[R%ǧ9>Lڽuz}҈7v?W}y_uon`M\^~@'Xb'~h +G} U|_ilq+Uq2|w.zJSgBQ'ME53IDb)4_Sqc™M+ר-Xu=Iu7ψ}{Idoͼ朣utJtkY{箮夓1ᚠ^S]gy(^}k Y ~ZWqj[vJiNyw S+Rx-eZM=[˃wǖ +}^fa_Tt&-yb9$-6~6QSV,.2QlVe]XѽKs_UQ8M{ϋ//9nsY}ٓ_ZOBOkrJĖg%Ms'OwzһOl.}8oC' U7_PVZO`L׵Ы̸n k(#`nȏГ“Yf>UaTqXuboXzIe;^lL-*svfl`0/Qd˵8N;+2P.pl`C?Kl$-tfJŭ9v|3cbϤ/~:mszI~mg%M}'d=ge~~2M;fULZ-u`~L?\,ޮ]חgsTZdwtYk_77^_?Uf&K$tkkïwM^^T5eJŞ㗋S^ +Zs]NܿUhEQ]em&=}!⑞͗άJR랊X܏07WKO˴m7^4^k4Bݗ*~'Inܝ̼N^ͣ#W+e59Pi^EffrOO5miNEsV}iXOrYP~'0inuCB@Sow=yNK7UιMk.oӀU"d~Ҝ_Wܭ8c .2)ϑ=0{U^=g%WO/~Y/];w][7$j*]Kw'STb/ٝd;ջK|`Q0姖[O >/(hNj%m[6Z=VDy1g|n8rS:9+5xvA/޺IA=gm :?em܌7*_냠^mZ}7B%l|}!UdvWo}]}n#kNr 1PzvE˶YLf1͡gnw}omok~FZ^Ԟ׏EJIO`$xu w5hˢ/Zޟ8cS@⣳Yv Ao=MM]glO+/ؼGjldzfEQXWatxW]{K;~۩MJ'] ]wTrQlӻ\ +W*7ް|W[ؿ--?+SgAqQ&k?.bB'mT\+5Z7lr}We6WLrL*gK|b$.nTXmm`#C4kvϽy%J;~ ޳rzM&IBW_X1\a+Vr<>c!n(#kb"v+O5xWɽSlNVH/TwKұVV0ᘃLFW![)YYAk7}=s{;rpMeYpO"M8\ձbmk8}o wwb_1 TM?n ?gi0qeƮ%e7NXݪsï:m]9j +N_%tM=N7-K o'y|nm@'i7/&.6=|MvϞ1VZ:V,`vLv ʱ'(0NzWlU*xL˯>Q^b0pܥ&S=wkLS)Q+[سLZf陡ڛלrF +3>Bђ+T|$}qCvl9-{/1,`dTB7EбbҧES_,!~:듼;>}QvO^l^n{qVo0?2}3/itȜK0~٪yzEW-ȪLWSn^{E<ڪ&~6M(?#jn羃@Ђ|m5.4lᶒrT9fԫ7%&[>%0kw\mvl_,*cTf!:Mwg#NO4&C,J͒o[]󬵭wGʣJ?~iz\\}N\}MW +LqʉJ;,ue2'S#'-qH(? Kվ8Ա3~yT[D;|I ~5{;Ҏ0 +rRwj.NzueZӞh㽶ThGob~Qzdj#JMyzˏW\#?4٧ߵ og=ʒ,{LR; wj>qcﳭڮum^%S\[]'h:&WyF@eNI ]uzڸߏ ߪ+7,\tz녏9Cғ{~SЏs=VS_ͺ~*m똏[y`SIV? yo:O<$f>lo֝}WՅ3.: E+2cU/`ꋅy + 2L=u/%octݘ3Cy⮉~!aUޟ|s٭O= V5'8j>NJ|$p} }3n??!#=Hpak{ʾwӵ%GNLYnsyڕgt]dGe2%{텴g~2 +lW+O9p`~yV*=}q"ǡS>Omf2C;klMޚkˡ`mI32۲Lp_=5z>X{SH_ƒ#"{;YVixm]xmլĝJfy:-}]jϪ;W؃ ި,6 a}靧dY.Ke_ƈ'KXc`woK/{UhyZW[sY~ TF 6iaB{ƿ)ь9= /xn9Ug*CT+ U\ߪZc{ ]b/q K8~?UE'ϛ.v[l&=W|m24^yӀ97/Y  -WoTIK2<*ޖn\qm;Xhoy. +0p@*u/g^kX͇ ;/7ن7ŝR^b|/m&}%eJZ*@“ 6LxL2Ho_t۩h9bv)^x[bQeGWlvmVf{N³6g\ +Y񨘼˪]diliGm,x%Mk?~|oG 6Ml" k};WÆ^oW|S^:3F"jq{WprAVOf枉mpTIYnuzo4I?ႉ O*.[΢´lF|t;\d76g+l$KOᖆwɭS,/|k;Zߺl;'Y)mweU7[F<[tU-a6VAyuO9/p\Q}2?& o]1v]mgYHY^Z횘'F'7&izM;/JIi%/,tLm6N=,zJ9ڕP9SJmGX$t5ԙjc7ei9vr=1nEװ*5~~>4|PاLS%`QyՋ2FzeZjg:^Z+W4Puw-#2Dg3 .w1%Om[0j9?goXug2sr{4iOT9\׾W?ޭQԳɧ-]: Vӷ' ~2lmXY$m^_UaG2Wtv:޿W2-uI+R jާwF8gȵ6Z}-^h5I^Ҧ3s)8Bƽuq"!^\1iʒObY1+.҂&=rYOg>VK}wz)3kH}:df)gÉ|+pmQDZF7Z c,by89Ů-'?퍊>E2f|w!jzw[Ӫ=}h.ؿod"wKzaG!9wq{1N{}e.=ةNb_:mO~پvM_L{#nʗ\=Y5/kCB#: /3+/RZ52ة[rGcoɨ,(DV7h"QWǭ67m/7SŽ .߷SݿKe[?lq&Yg5<;eI'us~MЩSr^MŋO:G^ ݹ1~M_o}/NcQ^{OcgvִzO*.9/^M:!SQf-z|_+g^u+׋FUeݼ2eg֣.{"tO[l~5%sؽjеUQ&"^ՠ&PFRu5TC}M.#ŧ񋍿fu6/".6։:Rdc{xad/~ٟ"%L{|uɻ?Нù?E^Ä*T ,O kvG5?+T\>B;|R5Xl4cqs%xwdza2<f3QS1[yԕW=;yӇ_HsGU3&r7֗=^@#NewQ"6h[^s4HkTs:Lke%KS!grngɷ lSVH`3B {$vc-W^^/Q~|*;MA +wx-ܦ+ʇd2iHlTk}/"&SV2OyQO˖l9y,J[B;!)_=$|}kwَ9}:&g1W?)_`]~mo|p=⭴<<,oD&Ŝ<|_1v f_#nl;}+K{qݥL ՟T(rvWj]œ-J3궻QbԦQYU}"MśVln/N^V9Īu%\+eY ͨ}Ӂ ?f]릩6 a|$$6]sE^[t絫dIL +aܼhzy?|{JjXȭW6V2UB{>}?W%p;gfԄ8dB|Y93pv*/7/͜vRmȵ +ͬU~ - 294vi_waò\VLjo? 9M^œI*nWU\yOYQWΝ&S+g'-)|yq_b7;$XaNɏg[.xD_oI/xDSu3%keZ?fZ-tѢԻN$&[O7[Nrݎi_"kyW3F +}d;R1n_n/̛p߸we},ljFٟqҬR'Su7D$X͛_z݆K'%{xdϔ7k W~ֹ=J\-?Zܪ<)2 |_8koȩg楷83)R2Rfv=2ޑw +?Pi[s\aԴRg:]OͻJ!H7u}S'?Q3}lbN3M=w-&*2Ӛ-Z%+zb/7Ȯdnpcr{_O{X:/:2Z*[;uMd߫*Do}LPF,`p]݇ zҺ3(=g9cxlSy34oњϗ3uN/:y]HƪNT9}jntQTm9oKm=3RTQ֠H-"V*m}D7w.ZrVP+FtaUuJUXH]:%F{obZS˳o(%Ǻ3jNiv߾?A=p.Qšco}[q~Ěw<[>)`^`gѥ9*0E~`ceS|@_sCs].W{;n-}JuĥS{yFnYScɛy2͏]>_@Al\%* Yl_kv( oQ=ek5_1Zn!C<3fG.[p"_(KU-[.V̿gʟQQٷ5抋Vݭ+ߘy sڟ +~ +0j+9M뒢{Bܫ>nrΒkg'{;t͟j?[zD;/GkFw'VsKط#ӗ?η[db̟S[̔$v\p:ޡzmY<o p%xT7w1vyDU&:P^s^Z~6o[@ЉDn\]^祥,}oMisͥUџw9.H}||ʍ.WVd-5e[5quGc-3s+&D,Yf۪}m`_enm^*{,ϭfBy@*/ٺvnֿzൺ=zw~_ݘtzɔ_wy1ɪg%XmΧ8QkvT9)1)3وGɖk2|mჩr)>_1k7cvƅ3oy'bvr]8W4koo*l˻MãYO,U(ZkXhdw6򴷆tN25/[74Y5Ǎ>y6c g8^]mʻ9`%C;G4ܝY?S'ꄻMk=<}^rMRk}9W6el[Kͳ,tC;\D0÷yO?3*XNͰfwœjx&㢖3Ko?yv?-՜4a] +_wIa|ar/iƍRk9쥴©>ZtG߸?w{ K5uj3,=4izPc݂#rKM4B3} +fdy΍Yr{:`fzF&Sܦ|^oma]?'"5 +ӛ1T\89+v? 7=j{]WΌuaMl]}g7-s*WxC_\|;i|b%W +$|O5/s)ˎ,pXDZvma**2g~! G';f /5V mhGoOv783vB?z08o_Mr5Yɵ25^Oԗݼ1wbdȦ' 2Ov3I6T|!5fW4v;s091cU.{4}yIܘ5~wR|0)e7|l撢G:_Yxu{a̸s {5d,`w1x̢UcޞU&hax(7T>r+?UywZ,Wˌ?gn9v.]Ҷ5uvU]rN:{5,ׇop/PXqhmEץyu!(W0}9%ӡ0ݓw |x|jyb>Kf+m5ެO, +-gkZgKY%?f/YƷM:5G8fukĽg ]PoVݱVf7&g}tp'X)5~'mC!ҤgKbA>8ѓ錛| +J9vVb6=9щ3Ħ~[s0rxyunf_w\8Sn;s;{5gg|QV,I^?P ᨸNև6LwU i;֞7h(vrE,o?;bm:xW|FD{ Ou?X!ZsWḲhkUՙG=NxϿ$l4˾:dz\گn~z8q0ŖUDıŋXNgM|@=3R9w#aoTT֞emN[ sd/omm-uY$5:L_zvEwUfۼnN+3Ϩ\gil׿NݶvtϘE./tzi]L.| 5oHO$Nyz Zo,>SQib?V_C?}u/q<\O=]g~Y2s5-T{ͺ}=|ߙW'-s0[5wTAD-whn?sKryINě>e6}YZ|oE;n:8\^" {"웑ehZsҹMo.w)\Zk^+K2V=&&01f5YGX5ϖPej[^Zrdn}R>uz,V/MMSRL}ԲE=Wyˏg$;$Eq{yٻKa|~7箍l>׫ŷiDgԇTyT^.2r欽Yg5Ϧ[_O{b y_v~W|yW70_gek[fo7ؾ(c=Ƒ~_.``rV¶gbW'ktW޺wǡۺɾDsE&f?;}vzD4u|iUbZ\z}Kӳ|;s?8}ېIU:daBL7gzOx O;5XmXo* Mθ8ӢhQU>Z6 ",u_ ܽ +-nI.8}I]*Xxy*f6}8 #Tx/M/f1i˒s}_8{f3@h78Uf̹lCNJ+YXy&v~3 eO}ͿccEԓťddm]k#"[iӛzȗ,)Xd|gWpYU=;aI]ѓzPU7/}K niccd7ֻYy}Yƚ7Ίp"—rYQa&Z&8󽍗~ienu.=#sW_WS7Hk-Z V8ڸ|o5&6ݜ g>2鸯1sz5>}oǖ?\4wJ۽685m:jaL95= eڦ%O:|&ϡ-.<|S ⮈Miӟ__=W5-CZ\lojk޻ SwGk+wBzk?f:ƚ0.,лץ%81&iw)w/ںG$GJ_&(z|xxp)G&)w/LĢ5ajO&^۩Z+|]71wlWiqY&{4-lSN}zaݰBY=ؼ}{NsM8$m5ZZ|ݛs0ſKA x=1uLjK9klb=+lW\Ipspq{I;gnQf`^/hm=#V8(?Y}˹/?Mi9۠,{%޽n9l߯nS眳~]4QH$j>Pr@VV& Lsj]=[{jM>*gU7krZt@ŹHʌK{ ۾_j~cmӦӲzo{MǗK9s"ylt}Mg/Kj(7Moe`U>[7bꖓ_F-K W{Pˎ}r%vW]#Ĵ׿Ѓn*+o}YYvȷ==YaD\Jxg>dQvigqgocV-gyuF=E|!OL|y=spM67\K6ڿ"f'3}&WOP`^;/7ZHLm~:nR Fzw%G} 9\ܣxOMxPC ΉN7:An ?tw}KU|S\lw|}kJ8kniStrLOu+fۑkXF's[C>ڬeP-qyz^{.~m5r$~-Vko27o?uy$SuN1;;iV:7t:-xϤ0oC#kf.L9czw⋊ݺ87az05ﯕ:~*oM}Ka̿GJhκq&DŽ\jL.?㥗wCߗ]SL49ss߼wu{k4UH 뙙w&v)KAMk 7>kνꪂݩ_Z,+[N4UnhQ.g:=UUK@w +N]]vng^OLБ^x;{\c?j̱nחRVW[lŏ +5\OڿI]~[cA# ufެsWنMIv?Ԏ\Uֻ:+։WUVF/?Ƕ9 N?7iYdNx#7nmk|0o{˶SM+}a/RwSΙ eӒS;*s#&6Vtz,wJlw;X33–~UvƇ|"D? y^y%1>yOE븵~XNF‰= D>yD)%Oz=W{s%Us58u‡Ҳe.۝7I;;|G+oԢY_O6/=k=˽\-L/Z3}!m+Վi^#rt1ѽsͲQ73->\4C+_ []p:1Ά2s?ΐ+fۗe]IyiwO9%OOZRc8_;߼jsGwoN}Vv\eZq3ZŶ&>}[V?[zk78R;&۸-|å5Tv5w|ըS(#jsW~l70}k8?Ļ?n9U;B5ȡ7}L]k~qqM-}-$_>دґaΏ\E|kVfgy2t~9g2eNYYk^-9{t[Wۗ,,)&9}WՂ. xiq&)u]*e͆.Mwe:t4z<Ȕ9n(y@FZ'Sa=9V|&fV}(Ŗ֌cս2\I ,m{EgHZRjox3gG秬\6[2oiF=ߖ?V[ZM&y$~L#w3 2*c{r7*Jн/w2ifGƦESZul`[wXGc_WZVx\ Az_[.I]fxho՞b.*~Ik74)_ruE䉵MWN^c&|.7_s 6x~bK{sqD_s5{W܉7–;].{5c_ڗwSL"윎1zkeEtv [[i9ӟTE_WYz¯+65:Vū*nnU {p~QtGAq'U}n?/ªot|nUj0 Y8g빑)LuYˮ=Z,L͝JqMl4_kn[⚻SR^-^nCilN}3/E1FTcdX+(k/dz;i 'sN}Q^s]S%B3ݿU$CXH@%o»6_M;_y;oM߁rۢXe5TO?asxgO }nN[y{9?5\/\w%vqgk +8̮57~cIe;'|uoK +H(jZڲ7Sg&>YSՊo ۧl.u)ǼRVa,Ԯ={+rC;ޭ_HҤvpacГXk% []qzFK̭N\\GYl8طO?I~yfˑ?VdqCS6S3=Yr~}S|7엇:fkL c™{OIJr`Cwwl{whMMrK.y!~毞 ‹bvobzqe. 6ß_9|7'ŝ*1|C6n{taі@)Dk/K>|*kc16R|;D|rxްek3d+S*-qnn&*TyK6Յn VnY̱t΃MF^Aq_lOY7i& ogf߼xSM6>w:VmMa`I蹜R0:҇Jy{'JzRC(ޙw6 =b~4Ys +_1%/+>'<]ee•mMpޓ־ӻ)"m~eUtNi,cյ.?>^byK~ϻvs u~]+=J~;QvG8zUߊ7ꝅj=Kdd.gL[zF˳!חqlK{+6p6UQί4dr-oc\Ǐl0kE&^p(tiE;z٧|7aw49עc5݇/_Lsp)Hoapwkߛ)W}/rfz +O_enҖ#;R<ιu[ت޽Mf*r˺)픑uZ^_/ Y{#u ]4TtN_}=Owcrb urUvuV~ b3T,GDkpvS,0zqʫgS8anoQA/_ivd].z}O\ɉGN&uuMpyq*8qW#R'~"׵:o>bgv,;r(8(^j{MlL/zfe 1<*Sz>[zt +<~2{c:VڱҶGl8TLC!->vY2S,.=IV}KնU.pqrLOWƒ?LW^vS'Ue^?nEesr{6%:YKȡEZ61Km4yM.^{kǒgΒ(j΃#M*?(=r z w׿dRt$=:rE!2Wh];gzn{k8[[%~[}薏ue{:_ywj2OU^gziK'T>2slF?l]W+nxHkIs̭{ؐ۷=SO.s_Ywe3IN^>%po_:3nsW̖ڳVLR뵳;`OϾrA9'n_.1 瓌lΗ-Dl-֗]5n[^yUWwN1A杖w=Ysg72TvO{{gLB8ޟ6_njLsnu'ASN5}1iewJԮW c5n+/#W _NL:twqGEg`!!L6+ظS?iQgVɉuC!ѤxcO7ql$az˕^363;lKoh| ȺK.\ص3=zv][Ҙ#kJάsF~0s>M] v?3~s_8/\aX5Q9z++̝xxN.Wz4\^|ݦY>v4/[:tJE9^U/,|Nդg5TĖxݥ|Ox_y,7)fyVc{}e7>.1:}\A}ܥvf_;ZsǜYmvt־p&KkV)ivzgm弹}_$eZؠwIWjĺξrzyEUr20[d<>wZ^EܝFM+7z?5^ڸ.*9&s|lsM]& -xoR\`))˙?EgZa>mY=t*ҿ)M]+L,jܒ=2Q6SQC㓮J7yߛ ƹcBZԟSm},벖,ztaTK/os|whh[sP*ƛYv%kٟ+l-$MMgLz/1͢L%%z_`z_YOF{+TUiL?rN㉊8j=-{Ǔo5laZo "y)={A<d_'-`(;aUz˨S;ݖ~aU֯mRBpLgocb2K9xXCP5L2i*{OV]Z|Rd^]f +1r5o \9N~2^y _܎{g2hG뢫/vOәern䅸 ̭_ٕNq"G(ۮgOn-9+0}C/ζյxco{7a毾2,oe g<b~3 _eS)䅽x#amzq.}=n]uWy`*]zI8`WTķNlZq1KΘ80p [X'w+{/6`]W1}we_[ɢ[<41!A?Ihn2F{<^ؿ]]/;Cɦ~W6Js"_wJ-'xۇFoxCzW/%9]/Zc^?yr^% [$lK`O;uVx=LqوF+w} q/7.jaZjO)/NpifDoɷ:͒\R(o}ح_WteLU6wǭYޮuZX\鳓C-mgwJu':v.{{zGVAx۵M{gcYB<צR)|OYfAՀXFӏ9vfZlȓ,>T#rlwjG@k;V]9?.40:{M" +-֙wZUvͳ[ΒGV{|rT&<:]eNiO.z!Fsσ+7, dd3ʔݛțsO+Hj7O7oB.rAGʇ}N=&:5V!~ (2V'|79OE|m~+{AJsMF ,7#AFGMZbא9w,5? ]vjK>YvpL_Y6W8fV+ޜvU{&ˑ/ROuj" wk=Nw0f.%|%Z +/??S_fݚ*Hs mη'g:׹{Sl4R>=>|9mc'Kv]zCz1sTI'N{]w&xӱWRYl .SK;bZ_ٰ;.Ʃ>04mbSëߡAe˿8-wjugWnpnOrڃ%/;+ON{U0'UW}h(ۦsZ۽Ʀ%!S{84m/ ؾ?^po,4vM`np:J+鶖KB_Ow5I<(fn>]߰}/-g$xTݻ%l{_ܥ_ZߴȝwI)%oh^~d7F&d|mJ/Wp|%߿\um-ذ]t0a̻, whdzir~aŲOb,6N[,xwm\_%gxU#+ܨ+X7'WnNB&;tKo21(v0Vq7Lubjӝ[)O(X}e%Y%+4Jodi |z5b'(t\?\Jm4h =S/ylђJx/m }xfysTyn2>\4CN@@m?g]`9)85&hgM4,EM͑>4}㎓f}e{\|Io|zW3:qӚsC.|ٽMmW.߾vQ濺/ϲK/gy%3Y0Y'_vdŷJ2jnܾ͒'歵>>J +lc|lm=#}Ϩs 7X[7d4yT)Bs[6u_nlV0D]]|Tc8mĽeViY>n=E-7oZL_}{N3e[s+ĭüf}pAfݓB[c}kJ_t6[%]w5ڢ-v\Z{|[|~!Ss;=o]]gQyͲVϿs|,&9i .;oqQEⷝ_b_[bzsߌzE{Qxhq}Omivܬ?fÇWw6T|#sQOcSm1_9!T'zquΏ̻Ȭ>ŐoVlS.[q>I3>|j|h^-fFQ7N2W@=YckefUn\{ͤ=s^+&s+}5[&8S NT`󆛓{Kj]h[x~lsKoM ڷqI蹃s #ZVVX]z7&Saq5ek4tfX1uc8n~SooiٴWMO&n-3O>w/[ZkT7ZK1F5i;G/M:}[璙 +[YU>=ֵr.~/w_tvGߥ]637.]n/ƀXr~_P҅sQ|f>Pr|ǐ<ڂO.kyY ?o +Uo-wxWE*.%:g>ٰLk/w,n=L|.k,?_CCݻ5O_13Sg<>{ŧ%s8T!av`*޻r:mW+av86{:,5&e\xsxW˫2\ +ި~wr~$_Rv\zUm6K~>u͙H~?޿)ȼSOF.>SvjN`}fY*r?{aDqO63'%j%h93ݗugN~I7zi 寮ma!ח4چ3bó޹1}bk]\BIl:&Z8Qο.?^uȒW-Fk_Tks~lcKԽw7.bq-ڭH6Wv$KBn4.լϿyN[TYڭa:n;w|{«"k/7 MEf(5j]5ۻG])veK2<>w=zwP|I.78tY?Gy>]Jե/=g=˺ٖ~f$kaX# >/(Һߌ3b2ʆi6Q|OfkGӪRZSEL͒Yx1瀍\RצYN+JMƺ^\bS%*{8o`xA3љOM#xQ߲W3h=to*I|uSW8$}Nɛٻos٫$v/Ig`.OOwp*1͓Szg8-ÔwURG$z'-NKvk|aO9*t,a5KOh{rve ;ֺ |ꢂzbNKW"I9~ECm+g8Nxi۝߲*Z'\=7NS1͋3Oya% WS=\x %z~. 88_CjѶom7|+puw}Kq^PR/VU1uc KJU{l[ق4KJ٪?,umٳgZ^?C(J/ ^XD̷W&S>|qFgf][P]}ڸ,_Fw|fҏ*'M3j4jsclTX\촳8_n +*u<{vC^ܢoܶܶOԎ5TSkU7fkkevxnFX 3vh?cR}a]{9JY}>9W9jYz>ޗ c%Ryj/w7Иڏ۹/yn^吩>#Wbr:>̷gE[73+W%^l׿r1 luOC%Wt?{>P$ދVq}:C S|M-23QSE#8`|A,V N +3^.Msou(-a5ƾ*n{:*{1Q g Ov.z3wkfcxz^^a׭g%=.pUqM>xLIW:rmkO+5>yjUPhַC;*/W5 b<6_WL7kHU~_gs̜ >KtSLBTS\\c^׭`o/5?')mXT^$宀xَCֹȸ wEgnMZ[)^S;gcQ|l.}{dRP?nZ"M ֕q֚,l,-|x4߼vG?ko}^輋"aU|+qweӺomΜw_/L'=wW޺ق/7fT*l+۶s&Z:fzl +O=})-y1S_~y+qY|~bVފNϥc"9~6s mߨޟ{e#w=α,nb)sp D*9nRT4_ۥwlޛ}-๓ǁQ\ὥW+׼?8;#еumӋ:2-=0/5-ތШ*ƅ̚k̩ + J ܘ$8w y?㎟*r W{'1IvV/[˃IϖJap^ФY"M(rfvk*Vۣn_\(9;(yѿKW\7(uYdvsukY2sO#{#XOƎi )z/T~eHTIx-tŎJJb,k< +`OΠI3m%m蕥R]PU ?wl_%R\1e#O<oYG#g̊{\wONE[:Ҙ?)~֭ ;H/SnӮs; Fӗm3qK(%Y!I–}ٚ ?~'m(|$7KZ,y"rJUSˮ630ϚcL[~v4`%'Zx'dݻ/q=⪅[6TfTn3Hݢ+ϸVX1dCggJJ7^61E 7-83? +ڲ>xZv>s ~w3}խ5ħ(dӰene{VpEJ3nXM'ީ;%, f =z2f-/,lܗp ,4^ _8=Kd}7]ʢj; |c׿߽kaّslL+zN35]n]fsC?/:"ZVn)Zeō};ɷu ow_,kw7m>D̅'.g +|?h<376O=$yόА2qYڦ'bum8#Q3W!}.[8US3HtҖS5^R&u?RKoIVr] ^ʍ"o=zH˦)m:/qcҭiټs4gUp?x<~=*dwsG؈zzi« R0ưl{飰߱We"zakN;al^=QwjO/--3.Nm ߫|R#m;bu 2uuЇSVދVςc9xx~(UvV>tOTlSƗ~U"q {Tmy|tٳWΏܜ"9]T[&ߐYW O2HƘgG1DN,u?Oumx%GwTrjwJ@Yҗ8:&],_0k'/w)O< wEevusukָC)whƲ]MxB59jLX7y§ڪӻ?7-u|О9[1F@~ Q/?ML˻rwB~ɿV~i\_]]j}CO[73[ul73*ɵ0])S߬^!LL?nVwF[y<ۛ޼qeꑇm8swE3y߽jLk>?N~h]Y>\5\w&w=hXޘl<|½#gMSQ?{vNq~xSTLű%[~zbn/ dV7<坹ܫ!ht9Gk2t +|5 7a5R o:x`ebm\fS?d+sʫs)J3\o++|o}}73ݖ]qu֕.Evt7ZWZЋu*"uK; +w.=:{[5]ד_,{] =X{Z1-*ccs2Ō{J +O>c<{w ^ms=v͜+ľ8ԞNj|B{>;Ȉ DQϔoVp*ZOfq,{;'ƼY+3u?̎k|W,unmwoz\fg}:=Zɭ.uŻ橤,duk83'0wLx{xo 5p-dn[)'6b#nR%&߽k V53RCξMjvvBϧM[ٲyӳD\m^Mݧ#Z5gOC=.!}ߵJVLYh,mEa.\P~5Sg0N#59S +nHOy{fwǡiw:L-gA{h8ǖv6fqWJusu1upʧf{)OFJ8߱hqpMlx^˹pp}vV,3ʊ*[m۸ͿpVI2ϛ"='[ڹx9kצ|O~۱Ȳev/Ig=}OG\9b/;,QwԚU)_{=v{%뻢Zl;ʪ'$T!g5/߿ol˧gTT6YxyӗfFd +mm>i$Iٸ Dn5eohz'ܼl_KX{|Κ+$5o_wZܙK~,םqpQ~wIkOz;j'34">Al#Zox45x-<7;g- ۙS>c7]_OAOWz>OfÐ`kœ/SRQkl_z(OBU"2aY'm>n)#:.8?xW xoYls$V~7V_vT:5*STgr3I:?clNwj{MYvEQ nsykn镚E?iJpl)(ZV+oH/:/s+%/Ƴ$9Zh0BI_X\ɶӧ1u&.[oqEj/xp7nm[Z{9]~-vNYEnnۥfNi6|`0iwDU<ԗiSb}_|?`]腝>mJ-gϲ>n?IsӒ5ZklM!KΠ╷((^VVD+;\%R6D +*W}w.q(Vw|=B/,'Ґ!JhzϥNz_n;|ʵ+}Wq XY.3³*UFY(TZs3v[pVl+aj|N~n}VGoٲmϊRIn~0~kw6]7[clc?w3]0ip4u23F%I˫LjztY*Ϣ;[NslZwA&Mc~.2ט$}>UAolJ)-_l}ū +Ǭ0y+u_%{d?ܡ~7.^x"MJwI_o|u?_gsI%n8)d/YS/ba=hy4es4Uޫ[jH]{OFy&S~5\j"8RB V3DCMͤ䘀áINs7^H)Jj+r:!E;w]>|Bde7MlQm*u6[҂~z7D'_%ӸK,R=83,WNo| |Em9Yl}iΙjuj5;D,'vOMp-;4V;fx-=7uڒ#]c8]מ˪N|vˬbCݾ1hf*OپXaǞ-k,^:4t jt66=eO-r{G&7]*4sw8 6FoY"ݎyI'^yA|M%ͿU|AoDL(I^-.~"\޶YXpl5Z7gmYCJJ +O=\B}y0u?bs}&fE6," [{55,έby(r]g:?C=ӽ.fX/' +b~0)k]iǮt> <}m=ѝ/ Dus~֏'>:w3GSe 9wJ~+?]6sS[yMٮQg%l'u0.gY?؄;ט+/.jФ1oNNd}zu@SnN`vaDe/)f:JG~ ֲ{}޷JS9OQdAOm3x>OpIK:VT:Kһt{NH Z4>\_b]Sk3i9wOrÖg~4O^xh59R+VgkԼPNĄ >pY-k&sȪWuߪemWv'ukXZeɟ-iw?,Jގl4|#W uR E~ϵ`iֳjn̷͖Ģvo;:~.ݵkֲ['=&WuF:][G YnI}薧Nknj_w{i& xqpO^PϷT^⬔O^ѿ}߻OwZL4r9z)QIi1\LnED︟ziɄ;Sڮ.♻pC# -}+Cmү 4T.=#]KV9̜,[2fmX 2Zy—L}f>z7UoVؓ^?0Sy<ѻ\SwޔlluD1sHrjҺxvFՠcT]>x-w=m/Nw|g}BeZg%ZasY;Xߥ3tZ&9柕 Gv8nqDד|y/IvWh٫Zjs`E7K N1>+G"xBgm*ߧPa9-o'RvH;#g#^{uwYoǕ/z^_llŹ]=$T]&hh~]El ڐClŗj|V?F -[mгAOb +K35_D_ܚ±Dd_ﲙU_t`D߯ޕ)O&~vII2ճ Ǟ|ܒ%eLj3xD@[XQw5[?Oib}tPd||c_7jjZ[)8~觵wnILkt<Չk?DNSWNįq_ ]sgͦ?ެV <'uƢ[p=ϟ=B˜e4U?%WSYԑC@>H:? >1dҹ }¹_9]7V+/K4880;`D|X_K_k咓|.OmR ٞMm>eA~}Eծ' +5|.r7]ChHt< +3K8گ]t^frID-e:3jsӥD|$n7ՙvڦ5R*H|̜TT"ٹwVYLJo3Ao f[H&,׶ +'4~+wkwoYF]b?q9kgZ`[hAᾐ΂w&2y +ݴ݅,E5Z{>|XU6Qr;U^6jlV`M}FZ9_0l5u:C';Z\Kj|\inWY5Q>o'0(s63Vt4iwNOߍ[-SN^A#϶,pʩ l) Yb1[H=̷oRu[Iͳ[(;)\mX]u|v79-_.߻B@a]YUSt/k&~g3Ì&ϣW-z8FoWGZ(4}r'UkW:X[sMkx&~ޮ}e +LSVܬyzf?߉ oHWup+PUӏ?{%/qR ҟf>tokwgu9?p]";MΓ)u0űMukEؾɧx͙xuل[GmMLZk~x#>19(+aKA32¾D+U;/Zop\$HOaS&9 UĜWIqNjАb}l=ZL=ǜ2CSsY($j]MaGJo{޹Xk`Y3c[za&[!8r&>.磂E& ៓4%n1OO]Ògr̽_rJ_5qv5nI"aўOALq\3)%OBeb]lW;{wa[F3FE^/ڲj2gHSc)ט^|KI|y '(nt,SՊIkE fW:՟׃&sښE/н{o+zjS&o O]qao~,wi.{{I%d#,keYYvrُ~+s˗[ۚs `׫)=&O5mٿ@s/~봬ZӞoHKSwV3sGjsɺ[ ;!Du2N8sK7w\}>xqy:YQ.,˜eߖ\aIUnŦm罏lSYbE2NmʪK*;Ȋ۱;^ YG`ꌦ{ܯU0/ܱ8sɿXE{?1?)o{o֭6rzk 8w.W ߵ/CTor_\:%7b7tPBL7u)#S/.QkEͶw.O{x,vVޝsk3{E*W2yYw i(䞰~ǽm'I_0M1aYu/mU:V)\kVaS3zril9aGx#c|nGn4UTL=+>'YNZ(c•wmѥ6-G'B6;mA_yJb} ]?OU`7p{!h3ޤy\;l|2X\cZw^!I'o4`|摏gF(rF ~c* ++шaem6.c6<{ix3h%suE;rgퟥ.Rsc_?#iǧWm"_zؗM~SKbpEܘitg -s]q9xfj,ZoíK w]u"ܲM0R_Mo3CA&'rKฮP9Pq]s\iGySMٵtW r_MFska7?vyne;%rV8VgܳK=ex߮+Yks',m>I"jf k.L|4MGj9XXeXNM,xH>*'sYrvkjjӶQ57ޫZm;3uUg-*s5~b0ݫ2ڧrn.cmVsMs'ehiԝz_mYgUNgy.ジ7,3qi8#TO.cQFbsƫWMٟy'?WidCWc&a;nL3^i}\NpGzW- 2OЫt{eU,3kz-k|cw/;89&&rMة~;s'^wZpOWhs~|.SrUkjݻpE [m .M?} 5s JDK1/g{g},tSt/QVrL͊g[opfI^Շ3 +8>8+Hŭn_.[ߋjvfiBѭ[n^?knBlm빿ܜR6Oˉk0?3X//Ԯ8^c{IE'oMgaYaz,n4ioz<,5`UF2';~V>w~ً/tkoaf? +[^sBSR6 T=ߥ4o,ʽ4] ʒr}T,<17u鯙5ON+6Kng:p'ȳ{ߍxy#^ -'UU>g#oSﮈݗhsvg{..aY- K{u"==ߦb"wՙ]s-oNm21G%[^~ӫjGQ>`,*>}ۙr'_Kxٷsk͚h%+BdwU}--=Ju9]a?l9WOOt'͍4Ld}|Śܹ4/XvƯmT+g~;T{Uݢ +GZW|V`qCt{~qMh>h˦D-WY\]T69o[)>WSx}S"My.zj~ޅS-[.R}/O>/z|㢳k7rJ~3O?ִtvΌƮgxk8^%깉'3sxd׿{kg3[VL; +a?~fz< k?uwwȿlj,#3<տ +4<`;3qu}TbOڣǯ~0d(4y%-[ͨ;n"KS&.=hsr`_Uz_;Df+d,*?q)/3`W8,tJ *~k^t|sd} g[z$v1ڬX[&grNXO_թ2M2G6j7+?vx{CK7{N[)!Wiqc?Mm1y'}Eb˧_{0˺Cr{g4]ߦ]o;Pf|o,(R[vL-;.Ƣ\p|~VrL)l9,o{_9̘IϟUuL9e֒+]&Bt~$Ugm}1z&K&gG34Ⱦ3^kfX?=*?/tbORpQssht"~CԿ{Mȍ\q~'c糪"ߪӹۿgŧв0:)!; \zVWߊ[ߡм,'nI|$Ѫ{}_R9ͫZOO~ltsִz<<ӽ-<ᡗnRn[L,wW<1̿Ma]D]}- Kogݔm"SZ';!S~݆[eOquuySo^b̧bdk$Yo/yֱڏ^=l~U)u f^RqÅFKoa6f\aRwI`'W~aTc1EK0Vcw]Ȝesѣe .iMn &ga:؍W{k!~S/^b36Az%/64kWz[m=Dw3؞ <%}Ч%o +3Tp\d֪˚u/d[g,s2M%[XnRZ6w m߽b_5d.KBs8ynt4ӡ3& +?㕨ebnb )[эԲG/^un38y9L۝wtHyjb[٣/#cQ~7\sɬ}JckI}ɬKUiR?vo8U~;^$C&IkC&vvqS2ۯ\YfnI{onW +^>dZ>8M٫9+eoNIX!t{*#nY|2NFصS_g㋙&:\qtfʄW#b{6d1Zĸ2 >_~1R]Cb;q]麰e%yN_nʉ_ K痙Ѷ6EntpBE;OM~4/d\[&;01d~~*5sV;s6kg?heN:O/6'NnR*U KeӚ:<\])25Mnf)i&[-<.l|J?Z@$Z LvOa3{!ׄM w.-lӾ/#| 6^Vp +^j&`4 ^mn,}|SM[Pnӫhr'BC=usi[1Zm?hͅI^ezJtE Ljw[9,Z\t/5w~6XbQ).V تxۂecr9K/)g\fEg{RJf̖Z?z>2\'sV=.ZzH0aϯEk4*0:\eP3mU,g,Q9WE?&v_^lMKrެ 89n>~dajߪ8Vg~ZZE[g_n,.SI8yNP=fw5=fO85-ߖi?\)f|ꮦ) Zm86 +=gSmᛞ9rs6Պ<' :뉳Q vfv 6w)P]:"#pt%.Z}c[ENx3L;pЃ)ק,` {"/jˣ=[e|MovBݎ贈^ +5 ؿi^3Onq~'7eLkg.tTyMofPtю lbO&C(a˶gO$fy}곢 +i}>|tD۴==Osآ޴2TANjʼn{ݿ&m\R+uWy:gmi$_o=J.Smd/ 6]lu)˫ YbA4Cyv +{c7 3qIE̷?7v5]ݶiOkK% &f%&= }`^6: Zxk +cܭmՆEg^ǾG뵣3kaRPjYϟxd(aủL7.~>CpF߫ݶxPh&ޯT&W}_=0l^ri:‰~w[Vܟ\Z<>G}Wo%-LX6kyO+_}ވϴYJAJMK[ۄO:c2M T]]:4kjiYꟆ}i{Dj)ν#{^YGF #G9)~g)eێ ]+Bu vِmh-%ט?V|7ڦ_G3*\#^yO>7ն v>2\l>>ng]Mz_Z{bҎ+N;gy7uJI ޭfeZ1&`gglk̥,fsMy^Tz%s.zyԥ/ZZ<ҿt 9vT;TI)ڼR˹ g^e޸}X6/, +pz>mQV;|[|bGE'|~eYzv} ŗN,_'WS3}n}(&W%":]ӓsnfY.Gr:M>w5\ܵ3<ɼ7+G3fV;eݭ8ͩf[V{Icf1G7/Kݻ"b🶰U +:U^'rD) +zv<K9jjQ:]W} <̒iY\HMξ*nS7ܼto]цBk?[τb6Hg3R/Z9WcfcL|+"p` S2U?{x]uқZݺS2ֲA7]]]p(Zy6λ@UlP_~\x ?d5͈]I7y¯ ,\{k,&+ +WsΓ;UvKgӦ"2v?xl\ü+E$3ravթ_XxP~SE}'לobN;e_e*6 0}$Ru޵ݬT<کw +9笽r4ό=QNmh(jl=,WTX٧Ŵ[$8k&l|Ybe.ԾHԉ4lzd9 +[B'4)Uxʴ\B.N=B`udgWy1,oo'q&NpN>[ldD?_fyc`Zp:^V׉Nǭ϶y3,.G+l&6Y\⼎%8?߅4mAΝ 5kJ./OJ'u:?`sZym2!ix ܕ6-ﻒO$y$p:S3E M+1vToM~yٶ*6n0$c㹏S TZ۝ɩB.iN]nb5iԅ/QM*wv)mNFì$ڕ|rβh˥[6zk1SׇRmo;;ae2O +ng)55efޏv~ub5Myqo̷VN4u{?N3uq1YAץz.){Ԅ7|Fv +n6SşFb//}w10Itꊒw>;"`2ւDaksj޴BsWXNx-~lijµyYܿNx92uR+^ӴxVۧ~{_xiɑ!{(ssWDa̩<4M+Dz߲{c"37k&brbwߪx̀[j*}vǗ=+4~:_ Td],n'ּ,Y=eYg%l$^|)]ymo\t]~!~31X=:.^BAK⦼>{kߊ,0`ҭO/D|zEeΤy7]S\*fO +߃צ9?!DU w\v;Svye?\9e嗬2݄m.y7UVz9S ffA)~EmWEK]SΞͷ ߟa]v9i\9>n*K}Ŭo>/(w4Ӣe2zpiƗ[_{gd[ֻ"yվ lhQ2k*uޱ\Fi_.ۺ象ry癘TN\ tWjަ7q~Uk0[S-gxŶMH\XG'ˍz?\}KlE +[Pj0A\=CvN }wd@bβn 2 Hk:.65J/#.:];`ܖi_|=yc$ԤĒ|XݼNI7&.B-ٯ ϋ}%4 #З{OsOg`unV+诱6k&o\~bt6V3&&weGeo#^uP@9UKJݝ؜;cbZ{L9'WqL55>]R,ݹn㖾}wJ:ׅY6V˛^}´e´maQ^؜֣EWtNo9|EuEN^U9`b!C®{_N\>%*߹eUŻgݿ\4!3h㥨+3qSy{wΟvʋ IAnflRt=G3wf_/vlR>5De װXssv?=$[»NS/khψe?b&6~jLfZn,zsk .vZ!k^픹 7>^}76 zȣ"I?eN.Y|eׯbJ}6=bY'/U_뜵k3i32 \L;=~̟!cy=um'&M7vWˍQ˗᧰Y& O u4_|!b(Zk•; 9 w-48i17g~Rcknj886ͬ@/gڻ;zOu6 (Ysܵ{ڰ$&c_IRǧ$nuv\IV-׼u7/qaz_~dK{گis6eY +-e;zm}l7=G\pxÙwXR)=2isJpЬWZll'fjLuO&/X?wg_71~3\_]½$} &!S<ڴͺ^n{҂)s.[?-w77V]ǐZU-ucWE/u{W؞.w5_TLK5%JֿS{pYe}D ۔FmW__|өSwvX|'>1 W_Z(t]uaȞO7HL%>sm~>ǴIKν:-lɕw2(tߩ5a!}!Fq.<6~̣2TSb\ f\6]WЉkn\sBzaϾ-S^8tw[{r=͸s~7,32R3D|^j=qOEd~?H<w:4珋iSq+f_ܾYha҈{3$Y=dsOkӕϺٻBFkIw¹O[_vJ_a5n ڣ~Lὓ桰u})UWxm;og>.==ת+jO|'Oc]yk˔+BS+TM+o“zΙ3:No|QF6lSĬ.ƍ& h|:e%;{ʒoݶ7:ϿϘ/$ny/lW Tw`}6S,+ NZ;.h^spٜ˞Ůlջz/++eVѓY.o([73w/q-:}]~Bg66AFX=i;d2-P/C_'6yE| _]?q}sF5O[w8_\{Iq)S|]p#Hi~"k}z˺q'q?Tk/-՟f|se߹<2snSre&iU3['dpYmzǩ5Ӛc6:\Osm_{GX/JrM9S/¿=pceS+e}-Zga[P{|_ouyw9y_ a\ՎWV+'4p@<".>νat# ;7ˮ '#9%"&Jqtʫ*Kwse)k%~[){Lg՛Ϋu-EG= {_.x2 mu:J6؞q-L%vJ[xYǗ\♏bV.^a-{IُY74͞ZLz+^<;68dfkkn'ޘ +}XV8ORU俢W~h<ѶSF[s9rڗoگqk{W"ouopm-t,GG_3+L,IKX_}誝 Ŭ(cˢ~϶&-hXMڧ{)QR,4 ^5?\̝-[xt7Db$s4鼌Ӳ +?mt>VαQЪyd6OHd?{M:"'oҽ]WvB?b5oW k<=?/3U2 wW>Rown<_ǷeKPP{I؅zd0^ܺ89[K–Nq]twzKOV{wqh$瓱{n&|UR|;>YP~ոyR'-^/&o2/~0ivfe3{:I|+ŵ 9tS!R&F7آ'^_٫;tE֞uyֶE(|YY0ɯ˜ XX.f*۴}W}Yܮ9~)Lv{ 3poZ;u$2.lGM~z܃*/KyMSޑ+7Ό8dϥ?>D4h}{ڌ9/s)=\I<{m7slc6IpC##nKS&759g毠\w"_5\[1F־,)SijzTdYԝHcj%$L3f!0sAMv?,w nImʥnQߦwh~@jyaC?NT>_&BES&ҩ3do3Wq]<"wDɶGݞt<vć̫\)fBʼnwm:׻Nj%ޗgM8Ѹo>iU%6nHdW{oW=K oo'\κ4&e_ro],Y%C(׽d_|%m]2(3 Wʄ{j\^'8ϹA)8Si삺zΝ:S [w, xp-zrE&tdٻ?t3ʗ/]k|szƛxYתzx]1bj} +}8&[wx\_=LJ&m<~3zuH;gsqg}*ulkI0(G(Vbs'wṕ^;w?x;¿ʣZl|Lgu>^شs.9ߡ[fli*;Y:ݧF;d)lQ_pOd޲؟[+U^3&sE]1Bϫra}5{ٔzJ/:>m/lL%?=کo架=>/(tysZ{WRT[yy>[/5D~bu/ny9uλSL;{6ͅˆ+uںAŋ,B%9Ge|36;s +Qj.?|9{V-OscGo&/36&4In|rd{-I$t| D8r^)' 3Ŕh_YM + zd/KToq Vن=)ubaeҴ)[V(Z߳[գJuJnz>(ki]_\ܥxO?e v`}zН ?%4)0 yKxv¿/:) +9w +FQvuN z-5UhuϺ?gb?穳/o?>:|ͷ'XWC$?׬U/obVql/Ku?gzǥ*o|f]IF\ǫWޯzvUSg_OMkMYUe纹Η_v1gO=Bo:}.~x y<'ލ),YMB.?&#[b{WL1i"[ KL9>޸m03eeV}t/{lbVyԢQ/33LbUɵ:z~ٶO?Mo>q%܏Mwvz,;j 0#fM%}gqzlw;rm|m9iw(ʞYln. ]e-߲wھu(ذ+E9)_teԒJOʉ̔6UjϛQgu~7yyΌKgn櫢5}5*nY Cjϗ0)z߁*SynᰖY.W'+Lr{I3?Z!ڴ"*tI[9bw|n}Zv3 ^v7{%,ݱ[:k +c&i4I,=y^`K $Nlx_ +_Qg6}S[ݮ-}%7qnҲmircĜu 2J NL 2:Y.:g}JRUN?J>֠rp`m +ocM95뫧?Bg!/LԄs{)xtns'7*{5yS= e*/wV:Ճ}G8}n!ly;oͷ*e0;_2P ߇e} jX+[t,gߡz/__#]b5c:"T[5BQ!+ {t1xDž1LTũ;az[Ss`~mGwc; v߶.qa\O+pOwMrw\s_J- )g^<{n֞f훱gòlۻ\5޴#4RQ/N_Mkғj?;7,QƄj /漦vW=[Y&'d`}QvǃJ/wS}絙 ެЬkRܣ,Qv›\G~5Z^avOWn_Yl֒rk-IZS5:,*rQµ z碟3]{AQ1~9E]xx&cn[Nikr>vH]fw9]&آ-΄z&\LMD*]ܽ|+Hv"(gՕ\]u=۾n +闎zI}`d12;&YzSɕO~U#sѵ3~8M98/>{إf٣<Θ,er,YHaXqmuSEyj>̇ZIoM .qNoWyJ&&:mM3qWG⃋[5irG[MܷA.r[=׺U/mO&,ΜfSwHw7uѪ7=a"%8k_"_^ +Mnɶ3Uس~N밎s61d^tߊ _}$L{ }/|g3P|kjY̒W2-\&-a/xMe +ǙP;&2R{Geq b|_NmEBkY""/hrVrks\t^iߝ +}I6houqgneԸN]ٻ2^7^V#*tV`PVB/ǯjvݮssыe=ɖT_U&Lªgʥ/ϋ,JoUs VƩqw`8Rϵ2UTxeo8zrj̯YSsK+`aM&Tw*f- r9k7|OX:+yb**X*l㠕KҼGefo/7ߢcm҅E*$d.=.qhd_wZX{LYDz.q,!X_zC)?O:jd`O;6u2v+d.(}D;͗ +W|wۗ_>@s_elV6Yk /iwe.*XT 1E[='6mdvխآҿa/:w2LخPR [xRUֲnVe5; 8X;g:zrxw~v}sHuܬ\} +K 1۫XcxNM&Z|S4Byw]{7ݗ7G9gdۺAXa]Ԫ3zߜZxx.|{QKw߿qk=g3o=vr}>m:;׊+M}L*x?_Nes{-$+q@1%:Mf&IpOܰw"\I/Sl֙jV[z_ӣfc6s_ؔ|pݪ{9쯿'F?7y_2ѻEI9K/h#rW{0n4ПTdHх/[s];xw4=L`rq+kR9h_rFѯW}ϲS6S{_<8V(}霂\٥975OOfE|f&zYA;?oG{T=.MZ/N9Osfq{n;ꪕ^kV]$BsOT޾ lʁS? _xKm')JZVzܟWxQ /Y#:K:{V᳏׿mUX{HJ=7g]KG/c/q]euR1~ *c󱵡kG) ɸSvhӆsW?3bWBܹu ͍ [`E.IZϤ)ﳺfvw~aOo(<y`ԒgF-Vi6k^%{Rm'ȍ#^X* řW5es[}ջ|oNGWxq:x.>w;%M}fk`Zy/ܲə,A)b+sv9-\Y#ϟ}JWf.ӭrǭ͗0*~״;X%ns Lvo9/㚘yό̾ ~UfSהTqe|VR=kVNwUBx罜h+KEzm?$Y"uz{έ,Mϭ5|BRϣ$ًhjOe6 \ezÿz+oϹ5oՏLT֬["8{ʙԒe#gǮIYR! ܙMtY+_iҥfMk+_A_*c۳? *euIj7+^XJعIj-'YOq{!xs@w v|mQmIWSg3NIV\b~X?9,L>[ޛv뜂̨KNLv{'fBҬ['|AmWT;~r +#pzm_(?g9&N" ~&Ϩa3;'chuqRi3~~ur] +;T(kp0e݉VOq34fDZJav[} _`)%)2s2-H\,A?J2=w WTݰWEl7oY\.쒜 +Gyqli1'R$=k>),s~3U uҟrvgL;[yiUieUPɗ6eY{9|4WzkKZğ.rcF '߼t۷&DCwvE$iN2|^͚y4\|AO[yj]l3B׃>m;=B+-?S4q 58$gW Tܖ`Kwjgd^ɷ\ӿKHhs.m+ݲe);wTG4[{U^r5*xz3U}Ty_Kd7ل$6b40lNJeC&ͯ$*˜4<,8-y`EBI+v{m8DiB[͛73uߏ*S?ۼ)R3x;[mg'oW.{JëVZ +3}<}WvWR^Tͮ-t{W{jybt㞥oŮzr]EO+~7vŖy:\Qg^ 3g郐'9e{OYآWU7q(RSd{ݖ:֫~Wqiǹם '}fzUIs*O#ޒO6w7ޗubJB7϶ec|~"^$dfnY-ݡxAxU_˞hߜuGE-+:c~mf&|vCyEY{m+49TW}fʻK[yT'6i{]"/Ǡ h. Ym ~Yz;dsu s܇[Y_}%xE_;5LVƿeK/eq}YOO jyݻ,CB;Y'߽byդJf~-N'O@XƺGB|X_T)&K*0Zնz;w'kώk $k(sL;a>'%7N;~ٜ7}m/~>:Qp6-9g5>,7WX1h.R &;&Z岅%w] fSA䘼"!(OW+|sZc{!N#JZM?!.};}3^):&ns됍K'lؐcKѴ5'WLoTùWSxH3;`nKTX#8bٲoY8}>d{֤C!9f{!w"+N.ago1+NuE1%?xԴo\?+5MkuWi}hj&3g]+svu>N _5/1>;#,n7 ~C_ֱ泊\ug*L>K.Ԯ)bl%aUt:漿Qދ'RIͦ{^Z%랞glcĻRv۱ίBCֈotNgbώҗ_m~'vuմӟğt~5&xGVĥ1oUK?Yܙ^Do0n&&@u!ͰՉ)Zu=},<6+xUyr&y˺}MvbO/tр ge;oOk[Kq&s7Ng_j^zo/͝w%WgՉogdl,XtWNDCwZ.8{wS:W +~^rߊ@ʛkeW3,ů*+6 㚓2!1گs}d6FzIͥ5}4}EbGZ+}je*Zi+9^n`Z=QǥVO:__ey0RҲgs7<|;kV~p?4?{\>0;2{K,zJ1v_^ڡrZ{W +mӶ+i:',q6p]W疖5;c\ӿj;HPs;NfðpQ7{4L#+\|ec3X_{ENson8xhbˤg2?ȍj7緖N37Bj, +oPGG(ڝrϻƢޟQ?s \n9UR$6[) Ɏ_r6K)S~SMX̍r*F<_c^$|(vcO8er'WOޏY;RsxlYyݮ>SH/{:noěkފ{evWFylUHCRl!)3Գ+<4|kQE[MMK`Ro[(;_:~U;_gr  {G?h/ `wo&ޱrPlZ{ Ӛ4J'\ 0U< l +29v:ajaɋ sD9]5b甠WϙߏRUYnڑ[; +V3.)X˒ܟ?b: {&_]gV_IWAr_,Ou?m!!a-{^{41 f)0M%ldL[)w"i +Ezv[k>}3|Fo^}-GqL '?SZ+;)ZKyܳv.m0Bks=ohY.+-VOp ?&zϑ2IcBk$x?T`C%syقm*ӝ@5~Wg?g6x%lwa޹'鿴)kky,$iU|i,:~=&q޴o WlrK&kZ *޴6l7`c;p0oǻ)vk/+d_^yǹQ]iY턣 +sNK.v^6kYSjw[y뮸iK:M~Cz@[77oyNc7'̑vKe^ΚRp7h'Z?hiXQwE|1dYy/S^\fkyeites99~ք5.6l&[?VsC)g2]_K39n~zmmu/ޙ(Ro{v)n3 :OUaOM?>WΝ(;0kLyjm,b'Vm:]{\}j-gQwy~|d%|xx5ŗ#g :La7PrzKTԽ;Ex>*.]a$!,a +L§3޹._jiօ=_<ƂG{.-rANzo7[ ۾!9I?g3-/eKg]1XXXRM\UJi=yt+~/R]:MߵWEofI7)COWɬ^XIˍ\>_` gWO}pm놫 ;^9~Oڵ>;yWR՞s.^6_e6NHtH^BnG!~o^8?㲛h!ũ^[jjPX̨dϘ_¾#:]j2y*,f^zk?֔xhOa +N<̐&nnWFQDsSJ,xyݭ_MT2v͵,0zJն04PJl)$ik^(%,k/}n0ӧ9h}]~mrɴc:ɦ'-+01WPq]Mnv9KQ9aޕ"LP8=63鿔j'_Oo:ɠ&PeOP4[ =F+K,>!]e'?>gB(wV˷0z~/9L~M5'?U༕yX~e |_&Ӎؤsg~lWMZ@M(-ڛM\3dᖥƋ {/hی/^rnMA9:|J 5l|0V!Oҽ=T̤}Ohr.P޳~u_.r^"kƢ?gœ~=tymxfa33,ͩ\ǴUśs_ vjh`Iý'=3.pxz焻7ʟ49ۅ{Oqb=ߎo-rOB/Vh6vϾ;_TG|),|W};^L8qm-3K' kmyBϋU5\cniXЍv={#&|N3ͨ7 㤽67xyP}9J": +69/0u_S͌ ^w/Bo׾<5[կ;ƣ{]o5:'lP>{=Y:QN5jgЁly'|~M22\Gzםqܾ/}]ǹkҮ=|GU.84GNfo< ĩpɞ7=7ol N5\|J ̮R߱/TiZQR^0{io_||?zD/2>)1-bݚ+\q1m2ybC{םޮRŴb2Ϙ{䱮R*{g8:6ܺ#JEܴ\B{Xo-;/)ma?ؚ8diҨ-rijR.O:P[Qz]biקklrRU^=g Qu:+ŖLE_lHȴkعws[`v!p؅qslW>ž0u`#Lq05--NT_^e}omvCe/O3|]6Z_ҫZ o)S ksםrr˻K78t( )udwco¥g]^h֩Yn?kZugS-mi.j;N;DZww>ܳwO=|+#{[JM[~ͻ\wWSoey$ޑ#Gg:xMԭis)⠔͎ L:ԣy̷_a' fY4WhOId2q;?ަPȊgwrEn2b jUhۆ ktNL4_ -꧎ +/U[uMT7q˥V}*Ԍm3EYmorfM~VaxRn<׭}(ɬ,$Y? x>DVMޠ}{ND_lfqO6Gբ$ruuN>v{Bݛ=57K̫WZɘY6]7[ࡥ-Dž.:rΩg" )yyѓ}y<_bzŘ =8&31{v9dbن ^-^g|j9G[cs^;;kOYoO~/ORc^˷QIg'/NzP.iw jU?8J,FL;fQU_6Q`떯,,Dv4xOnEjًpruGK 5olR3vOsw\-RGbD 6cR sU&`ӷۉW&-;i米 +Sُמ =z8~o;93;җ9;~U^47da5Glcyg~ c}Zݢ=}2/.?SԴ4Ń;/}Yۯq!Ie,=mћ[Lgq0j+Vrgvs,GS`>qiڒQލ +[g.;mѫ7wnT/ubw w|:}_:+H;2>[~CW?e.)+ZĦ;,[Q\ʊ +sdU}42Q[ygRtfU+y/3ې۱u2p Ř~jofZ_,y"t}&ٸ~ق.mbzi0ϧ+/qsS܎otU\u;}n"yͫ\T\iƫi K>Tgzb蘘{S/ںDkЉ~V._6(_e5+?-gé~q=Ѡ?N[RmJDGs۳"O/Xz]ߓ |c2m{ŭs&cHa ?wҝkWK?{ۗ~I;x%Xi,» -%ŽKd%~ꇐ]b]ιeƤ'gi9ęSyS6I }==+^aV[ȶ[%Sex4Wq~R=Y.(Zb7!ErsZOM(*_gOp3n?5;vT־-co us_6;pצٳa7y慼ols"(/\ZjoV͕ΎgqԚ`NRο5[.LUɾt[ʓ{Wȣ`݌eg&ĵ=ҵ%{q?iX'\6jS/9lty4kJeZwחeTM:?W@AW.0mcP:Ke]o3:7%_G%.]>8WJsK/f6;|qcsFۄ][|9-k3* =4#Ux| E>x_i༧b#npY ȫg+5Xv%5,.e]{ZaKk|B++'8/i63{j,5gR>y>z?Y[Y11FF Ӻ5l7;:gU~y9l% RSNn_aƼz&E8c_,]iQج?8]Ui]vOo5B{S8C|kOzoS1*cdf[hyN忦.U3}8F7|9sDx(fbwʲ{+CmJ*S}fG3|RN:1A2?Ԭ>ew;=2]=LQl۽}Fw"b_VO|_!iqǽ6Z|ZZI񉫷J2\t_aDxD#޼'7XӥۉvEgԭT_z(ms O|&^K+dfߴ8%'4j<}4&LvuxJt=W͊ifjv?T;vߵ>In;me߾}\t/u{ǟy&1F~y0e'ss 2M?mLIIOC#;fw5gG3l\!m_.ƺ/d$<ѓaIjh~ =b٬嵭rL/خojJ3|郾JM6f,yL>{yAnGr^2X2<&Um 9ts^Y*ou'xwy'5?T|vuo5)^gꮯך"G~޶53#,7k`RU*gხm^ǙDݝoh3Y^jL$p_iB貴{˞YT%nMsǗ_Ҹĝei^V՛Uic_~bNiw?ƻa< ]~cѽk/`Ӆ ~{NM󷯜װvU1٫[8V0} \ +<スY>jγZu,gq{zjL{DzaKJQh6`Sa|Hi@`Ufk f2Vz0'xCm.|]cbU-zqMN˃6tԎ U8c=e7尥Z(] 8 2xMdb pA+$w8ƛ.Q .{kɫ5ї&}}jr7IݱxPǏKĎQBK>94z>}ھ͘""鏖0wo9{JoJtFvzEagO?tSƫlwᒾ'ar;]R7mr>#UT9'229wuLs~/Sxt+UҬEa uV3?nהҽ=d]2+O8t]?<(j{Gs=qJm:{I~W$K@ƻ巨niU:Z8fS _ߚr5glл5gsOd?OJH/C]Sjbo+__'lQ wF.G4iG3|D27Eᓧxty^Ϭc\0E#7m>J[ߢ=$ɴ/f4]dDV&ϐW_4-EнƷ cѴX׋ڱsz4_?sv~>~*nQ4W/~771iڒ}Z^6, +4>Ö[ξxjoo_X}C{_Lk?x8)'Lz7z\y4uM_.)RjsSV^5\lZsx#K>Nbd[Kn)^W.:zrRbL&_y͢{'1ۣn- t͙+Q_|6W#O&L_E1'g[i*sճL9NigB>}k7eeC;:f/_zr"*[+Q7 Q[/#!|5:r~=Υ;&ƻ@dvƨj!Y25q\gw^]f92okWxX{AgϧŪÎ;.SwƦY~ޔmzTU8\*tae?} +Ty-CR/2!9ۙU=g>ig1^'>%?CgUV^ʳܓn܈ ycOξ~iek֩j'"GC "d)-rۆkD9}LxC3{OX%FjV gc룊H^<__7[p nj߾!n+Sf 3~Pw=P%uuu*=ltDߍ}_÷pǧf2}`Yۤ"yU) )+ּ{{%E '&~6UfML~=4L;U=5!.`;_ڿI:K}VS8*?ꓣpExO,uBKw>ܽatJ?T T~O쎉ޯWn_Id^^<^es "9Z/={j֛oO+%]JYśWyt B_os4ov|Rn^2?mr⇏|%Wh/ 9?j͊'kYyjtQV֥>\{=u58v:Sww\n5VhICsREo{v(jx?|{&T&+*Ht5[|/|xq >>(oɴ[.w%/rޮiMbS$uk_󦈋μf :ݶaɷL%x-և7\nݗ;t̽+4`oKH>cIL>~unEu.yӌ쎅Re?\=|Hf(&?DjPs>.3|wO_̏߫9{lc8z/ٗ떬W-Ω̟7'cTkߤ>{\,3'0Owy~`F՟lmRʖ>޲pS='9t!nɒ&U?w|F:9ݛEZ4ugj{_^{g5v%3_ȰR.l{!W1YvUMnE^O=vrrz3 1b>./-n=q_7l?*[>"]cCwkMU^tSV vuO~i=l9r4O0t+Tޘg[}EG\^61l >BiZ[7>rcP[gێkz"{ґcv2(ud͟O)h?Nz霺o6G|Ȉݼ@gۙ + &hMZ\c-b~nԽ:Gk{m_YeO/? U%YӇ߹?|_zSq_Z :{QD63m"d-0 ]iޏZە ԩV{V+H^$^8I,[Sq? tv2$:~,̲z_[O͈A$vG_)!W_hp2ڿZpVn䙲.ߵww_RrƯ +U39>5N|dm]I< EOfmޜ6?ݗ7k޲ƨ[q'8R՟ٹ +m2uʶ/UlSSywׇ0-9xbUĽ;XM&4[jq s.{ݭ?O_x_a>Jj}*0:tgK*׆6oݒnu[dMOїܦWywOW{ꃯOOX$娦 -oS?W"‹_ wK_c쳣#gTb}|'~w/#>PO}89nhgDUM[m\s֓lhX-N?(e#֥&<(SwE*m J +uIVaL=N/wL51=zu8;b_pC}:=Eӛ p̙hZ)=qOLʉ;ah=OG~|r֕?Jq{|o[6W;'|&2,sw5~7gɏF[8'I$W__/%S򀎒d3+ޝ݉C5z&*wZÞ㊯rJsq0\s|M~\Z^\;sY]օ=usA% X.<Ujz~M}+bi9Yٲ+׾fr잽;ݒM/n!rM,Ok{۷dUwB)!6]7~od>^)w4ᙖAL~R>hpMs?)xpQ}2\λ*R$F q ZrCI=4f_fO)}fswCһ+k6ܴgS$We_W߱A,aekkt+5|rڸF)y'O +x\!eҥe qt44܎V9"d㥕Swf^Ґ{}c'gD(9g؁ J ~s.=aqε|,kMv}*֓&}\s-puC'Uά3+Peo+~멭Ś?=yniIι??uǚ>Xy5?/=d|DH˩$ꇋϱ7|ڨSUGs"tgsX+%V(.T޾¥4K~oO/|j$ha53d8HΧky+yTJ~{Tzmn +lU{78`,N50ƙu/*V]8nRvIrx~/gz=wPЪ;0~g:Ԋև +:3$ sv +?n4է1<ʧpN)[Zol(7b|:qTI]f<}&坒~(|W;^f~ꢋ\{4S}W^D{ ,9q1}e9kԍd41yMYJzHG| !/.c[l^ߖZ[ +'ַ?J%_㲹І:c|OV{>yU=.V}:»yY,rN?}q#!'˂O[["A\IF' ݼi3o6N +ygwEͳ"| =}KDW~S?(Fr?t}~{Ͳs$ٰGdϵ2u/vY8/X~g֔G52k|84o]hPRiA3ɩߟr\WY{ l]fԹ~޾X٦l 5eo-y-g'n:7)Y}BO6٢ˬ~-u`]G'?5m5k^2\:o~h_l{ 9v-nմmDy[B ʒ7*>J]6;T/}ڷV %zsiN)fS}×6ؠ'{Aͳ)"|m~䄓ƻ:k>y˒]o;_=ŵ}S*Mq߳Cʗc'$+y_^- V/C>({۳b +y ?)3/rO?ռo))X]- +]P(ݾkzԬ[fX8o{Ūů5~Y"x}<7Z[o+ RޏϷ4H I|qqoroc}`aTߓb5/~j;kV}]O˘'8zgk2{X}$u#[lSK-8e|MV7>}I%gRxwKfNsy6y.)1yq/\VݷщV3a{{!u6wk?v.?=Y/w%mk]մċcuJ%c)U&qɧ'WGe~m{}oՎ _[[ٽ@i MW۞X4;L*Nn棹jVO M_#:~;WoXwemMv"ʛY߉u^4w; ?تA^ɛF7y|=㓟G n.!B|%Lcg;}"WFvM:zL(#%!ƫԖ2Ɲ;vϢ uNZ2oƤejw|oY*ûCsW49Nqmd#ګ9{Uˇ~jk萹M>WH=7?gqW߸=VXQ^3ڦ%{I;3^t]e2+(OȎ^Gի4^|3Ȟxuޓd}f{VY,0塂!C. <=ڴx0#>LrWmKU}̟^_ҝ|Wʶ.x{ֿϾ,K4;S;ws=y" i|Ykp^#;^Myuthɡ&+i5rٻ=>e玮6\RR!2vIX^,R?1+g^Yk>J K#m"[$L,*3o\[&.qZxf4SkVYivM5[l%%}tK1Θڿ}Wzl^~_oS=ܱn4^m;>L?BmS}O ʢ?Z?C@-mڧ+U[Z&yAfFyuek̙ҁ[K~ft5}XKozHg 'Ō+f>R?R+`sϏ*n rᴪ[Nf{y$kf/cP`QAͿ^c3ϑ7?DD);(zJo'+P'$r҂]a|s=cQS׸k a/'1IsV;.T{†DSj.M|cnSzNwT1VV]?s-X:舯Lܸ՝ ֥N}{E1bIbTf:[ a՞o6T3yOGXO9+:7=zY'7=iwoߪ?}۽9)'LUï~?Ywמ,srU%w~w9szlUZ+էyMk5hžtLLonqyqdiy1T}%f9&\~b1S*ڧ47Erm}~zyߚ]ƺpZ8]P޵6Jq"wY~S4d[h+V?bX8hyM>>U63Oϸss`єN4x^e^uO)>^>kBnû!b#N^1o|sq\7I?&'_Ϸv|*es;[Ak^ާeEw"d*|4UwGw.W,i/X'!{ ˁi.̥e |튑Ѷeu-m(۰_\`κ5ʅo{IܺrѤOyo=3?Xҿik!ykl8pɌ7KX%lUrnpOڳ|%=K3U33Xp9a'ko9Id6WZ &Hˌ-oL<,wK+,hS&pz}ceM+S߲crWPJmbw[%שk뗢3N Ҿx=o,9I(2_{u2>[zbĝϻr0zFq\a ,<ŅOO'V^ _'e=ܓ0ڴRrnBߖnh[<}1H[Ys }<+z|w)x׷ 4̘%y3/\zb_^튢g_7w9pE|f1.Qo&-{I聲ƴ EI޲ѥ)uS.>hZIJ6=e?ʴ(]VߒIHdw*  ڱ#VMwߩɷڰȑLB^(7CaieyB +Z4{7| +eYUe1 .1 +ڞfdVcl[(Ht\Ot!C5]A<%q;(y1~4td{y?5A:Y>PtߔU,T͈>ޘL3Z(n m32ϋ[WO`dYSnf6K +'/zgU,NCŁ'%4x~KmN-7g߶uvsKBʲGeyS87Owf4o9]2yO NZ!dY!#zݾcv{ZX_¦K+E,$yyObXE#^>O߉s`ന6[Z$)dgTtVA3VȮ+N>M-vP28dz.̽cv'RmebmSXœYM̑#h9v?n;Xw<>S!pRy~䠘W}1qHITuΘljD V,Cz:۬XoB-پs] +q\R-,%W͚tFgQɃ]9}2Ù勷6~!"N?n{bvXl ?Gf#.looS{gF&^Ond`ss![śOHz.1߮'nWgԏpr#zu^ЙC܌l>-~[|wQCH3Y-d^>} }ڸoY;rr[^戻Y2_qU Y.nLc;3\who U90myӇ+̍2Jvq|!y>%mS[[7zO{,j-v9S}UF,LczչYg^tb+nyG)4ϕw`ܦwZ8ŝ;3A`l fa6A)qayA[x̚n͹m7癅dp~޷9ֆ] +:Z7AԸ?i[,g%~}X3&:6[*+9ˇH͑{><9坡Cho+}ΔW#Oxox\׿X|*]iW>J_',t&kܚޫTw ?Y0%{jP /1_vuRJ"ȟe"]*i,59u.k}:g4U{(eѺUeZy;dPkA/nmUZh"+t/q!/0X]0}m?|V²zݡg7&h8$VvY.8-?ݲ|Cik.?>Ue\FuJR(z>c!s-%l~G|qꏯ.bẃEYIړ'fZoՎ 0M _ęk/{|:v(`v=W]zmrjcO }Pk-bz@ڠANgg]R)SVJ߰*9vؖu]bn Nbb>8d G}xo;ݯGX%9ѷ^%J)?^wiaEfͨKަG-eFһcK[1R_O-މOyw߬L-\`߿hnMn\S+b]Ӫ&s*xPGKy}ǩbץi6]|q~lVNk8[-t^L]Ӷ|OWdn C^ +PR(}`/覮%kb]<'8~w~?hӎ›`訶> X7&h5Ͽ?Fm/|$MܘW1")+{}9e+ Y^=KWn8f'rJZ1s_1é?lrkBv_n;;k7T~ Df_;keFv}\78qzn}o }~羃+y /[eʽ 4EJy/3gt^8n"`}fxeYj 'H׳~%& $=;h[CISsKz}?AKZW{3fٛ6{fX&AG[tnZo>(2մ$I[}me +;Ƚd~gCL܎E3rwpf(Z6KߐlѼ߾E>|owWeX9pL\䯪q O6J& ]'qV{ZM8"`Gܮd?cL ngm}zߩW~ux.ޮq *NQ< oZ&G\.,8xS#2oɩ\֥RׯRXhEr76uLr6ϖL8\myϴOD^8)ȍ?V㼓=Nn'J>V]W{Np]9'R}V?y K ٬P~+f]U=~jI9!ON=rU#ӼM'w|]v'Hr׹ O* P\~u† -YYZT]bY%ʒ=9MmꆪFb\26>Ņ勩l}>R_/69u6Z7Ū Wm|ꎅkOvΚ7|y36L~?7_O7Og){w~,Ok-j1OZ6M#Jb8eﯲOsJݴa>7imZ^궫͚V99WߞѼ5h{l&?,ۦ|xaWܳn9/]x>~]Ϟ~?wó<; +i|JqPWio[ZiߗQlwr6 Gy6tdֺm㐧VB%/o3= +сUlS8fm|[=3/ gϔ((?춇g<|?Ӣ]'lhtgpfU's(nزR\çf"{ r/)|t ~zMDܾ`^{BN]xOҙᠶ7mvu\ڤ_ؾڸ=reWWۦZ\u/{kB-[)}?}/QxUS\,Y{Up穇0~]Qz_:ۭ^^OÒ75l͚zby9.̴3y◛r}#+hv!XpݚWo Nl;Jd',s:>>;@SPsoB]g^Y(7׼'KO~wڣ#|K.aMk|ޱcތwW”!UzX:> +>2'5ZwLj"Ϥ93i{zKV+=5ł&l7X侯KK>9;^ۢƝ?K8N\8{r^T̝7kR˷>ӗ:th~$kiq7ڮ|tMqޙu/g`R!&g cIvqA +q?yaqdm2ׅ,qZ/N2e⢬C^_V4.jd/:truiy{~:Tx}ODMN7Uluj ۙ媑*#6n>{)mm摻TwzUTYe2]#~ސSYkIJcm+eۖo<0rayL; +_{5Sq-ճY_jŜM߳Za7f.e>v),䚶ٓE≶i/Uk#}=xV5ֺ~cQ螅Sk?gYu'W--cȱ7< "}kOpݔ/$@Zse^o6wUN`\&c2`vzcw؋̬#m? j0$n+^Z }?YE;j'aa)֚jp/ni]wxA]W}\=i |ʬ؉U +j-a~3\Vo|9_&Kniz~Ym7d,V2tMPƽ1IטJ/HϡqLwC#__RAX ~vcku*S*6\ToRr㏨%&1Jxi)^o`Į3קꮹu}SNkzϽ~צn6*ZyqsڵIkBKzEJ5x +zW'yM8T jxg,tH ;Hr#-Vo]wcl):Ÿ*R>1_&[T&ٚޛgoW;8Ao1֌*\*[*~$>Ts;͟&Lߑ- /l~nwWaD奞;SǿheNr~1[wsIu+6 +33d9"ۦ'OԢrmڽpy,}wf:͓_.g-i-͞ju+lSZvݦr[wF[n V&E>/1TQ9\Kt}řI3MX6>OuMu=ik-%k26+ .g 'P_9g[u,.)5:Rp\׹վ`Wr71ys6w{[:.M^xBֳ.Ɗ,p|}BZo>;O.es& +Bii>*bӸkOAAtʂ[[;l>gA˭3h^Чg@'c:%E>+\k_ye'sQ䠙<}+G-GtW_ƴS-]صR{uǙ~uG5H$.YvrKUM/?k--WOG~yKǿۯ/ǭ-*-FXڵ~tT##>g_t.~Kꑞa. +k6=`8zeݓ8&hL)X_[kiZw[9e[qa=Y7܏Zg%{yG?ݴ=L;sKIw>5q +U>[gK}9̪=KCms!QuqRL%.bfq_Wf\mY*޽޹I+V/[sX +\>cWV9LUm3].LhZyB +͎c}Vâ,qݞ;u0曛pֽ͓*X.JS^r!uCĄMQ%n̯`=fj/У+|.uwii$Rw2zF5y=}5u^˶~QЫ&X=jJ%~V~08$Dr5\^%:jSoYrG޾jqz7fqdۿCќf5yN{k +=_.; ?r v}fLY!Q^ҋ[.Sx3VU8)?bKZ7.D횹{sU:_t_z\y꧃h u }4ItJዸ*gWX-%b)II9[f+IFYOw[zº$ŷv)뭓~Ҵ&7_\1:__wwƟ &.Dʞ89=ߥ **j_^԰[l~G˛:z+Dz.}nqտdQE'WM{{njo9eg}q@߹2oa䌭lg+|~ϚfRRCk .;ܨaпxX^]`})jz^yxr[~Y{f 3-={X7 DHg/ rEu["s_m-*Z󶬫s--0+!kylzmQγr7-*0v? jv}iLkr4<{]Rȋ2;1'~2ljwK^72Dt~oO6Ow(8EL햞oY#R*~1k[a`zjSaK9'~_k| q-7XqNu-݉6kqgWF :=e^zuXpw!wW\yQBėy%,ܺ1{Źu}W͵;յuم mh7'̣4? }";Yg%F|95EgċMsNՏ3h,=p|_~'rO0Q}.ÍRWT3iXdyͥT~$ I|>wXcKӧΗLz7L[:ӹ{ +z)e;!Y;$ݏ#]%/Wda6‚ Si5ݏ?<(=kڟʙϞ\ܲw%]o6̨0_|Zc{ 7C縉9uʒ@k~Iu~V~n9g≂z+ YOO?hjw={ƛC> +,?(u66&AI겈+6';9ou(80˃ 9E&ⵓ?x9sU؝,u]21Ozu4Xe'_fX-uѢCk>ocDY6N]WH/bޱ;Dl]N:KLfScR QOKq{uu9ZnMMwx+LJzfTI=m\m?1Y*æ_^4UzK5Ve ,qm&wi_x26ʩq>6tcv?,m{&4+dͺg9V6>T*<ū'cZ!_ʽKJ1[IY\W}wؔmQ~e v2tNCSgӗ}_S#k&U#5ŭ꿊jvnՌ]sV8pR:͓72.u]Op7O" qT`r""{z8'`ʊmm3f:GDMeZIVKGeov{%mafeUڴ <̜jJ:?z˶kńgNq32ɭ(p)˶A=]^mÇR_,]pe:V/:oթzc69AqhU=~Yg\daWý󜍸1pJZ))u~6`.kX`YCgsQ}q_tȼs;}i &iI_瞃f{}sZdjmH;e ߞN6^ոwf e z/ْt&VaU֬gsNJ\꿿iAUy/bo cP/KƸtG[Is֕hh4(, sӷ!vog*P +7^KdV{:Ԩ%y_s𲈚e[,󱨳5jI*˶E[l8UG b^p}N^5,^%dO硌f^nnkUkJ>]&cXtxb]^38ey[mɟojpH,(W̏I;pl>rdۛ<ǯI +Jz]f޲jz~O漬 ­35eS)XD?|}Mv_%Qr;ReO7&Vr›3mGVH?Mpf:+m1i]}BR|^A:8x*dX %G7/Vu[wOߟmQZe޼PO0q^av)?;lel*=gO^ʸCtzιW$}xP}i%R[dAI'尿\7p~Oxym7W_wɚyaT~eioԺ5΋̞ZxaQZ霦GlLrZβkqW1/o +k|9_6\'wʿ;sѝ|NI| +NmIx隸r9w2OAMByk&/T^ë1Y̙^=K~pjǘ-YSSϭ(^k3qk,-Uݗ7siNԂN- ,78$ߜ7} VmM}]OW}>sxr˃P k./vٜ{ϯ :\Y KD5OP1c׽fI+=uۣC/&gRҰ{n*ZsZȖ:'?eS`unV_ +|sާfZq<b?|^$zE[Xvz͵tZh K*t\7+5ݥStjlUɒczc.:ǟxF=11M^<&m;㎳c#Vei\y1'멼zfSnV\^6o۴K_W^׹{VZ[dY73f"RSJx/<6ʫW| Zڵ<6-[ O"[v,};KbF|9Obrr"MӤ"/\X%WcyRa׉ACHn3m˕:ʳT=#w2*%տ,I??]svLgd,>ف9',2rV!²{A&;QېIWi,0( du,uMSE4M_br7|Yʷ҇ZL¿3/FQ5oE$?Yk{O/b;^1U{r.J'R**Wc{!ΡL/v.7zlNŝ vL7{\b\HQ~/?Y؟`eqZ,AW<k-+n5s[_ k{I^gpMIsʘk32K|nI\UeuvlZ1cj{?ۛ~Ȭ- kċ w-_f--"=Qk5ΨXX窍=+p)ԬXoٿ(=бpeJu~OH-OܥUuiL2?gu[!_m=+yeש0k >``H=G~y{$w)a=S5{[1{{*B +Sb/ֿJ*}mi%]d1-m1 B~k|Wr곢s_|x"ם]O2&~}03#i|1W_#t,iY?&>TS5a +5םvHu+S֝=Bܷ  /i`rLkǜm[*=]dӍ귦D_cԗc/ b'>u{ќ!'¸3 ~ȘNk][kɫħ}NVmӊBpsBn솴|k5:_.̰[ٚ+?cIz@uGH>i<GGڣ&){T"ϽM鋢w{.];>/`d +Ӎb[b7W|?%F؃G)+Tp[_}'O%w-9dj(;QcG,= ,K'ؚwގfzʑ>f?wc0ϟK&4;bzA\ݚ{XIo񑥧sV+/fHX=n },4>rM>t>f}Ue'KyHV +R~QpٷK[f?wlű//S:`oK2ӋşEh/}l1 nnゎ-#V&Z@а6,=ҦM͟g1/uc!eG7;<淏*ǔ+v?|81!çy#5)v'?Z`ş~8%]+ٺ&7{5wJZ8-iHHӁْVtg|r8boWOUG00\(Q_`ԣ!u쭵?&랳r@ɶ+k6&*q?x=yjF/_ĥ(f`9-K꟨+9o{6eiLU?Xu?廒>>~sM^siǗ,\bv#3M+-"pg}#SSճtgw޶Y I?xO狛]Ze}ۖ5Q] wɖYeP4_t-|u,q?R!uOOl3ǩ> ΖBUBrLow0<7Qp-ۗ;%cz[ҟ]X.8my$ ޹}Q5+5TqtZF6wo^ N˯{KjNcbKMZU^m g'r+|cQڢh`:޻<9a}3w]1K|__3w{MӟF{߿`^hN-n:zqz^l:i:/8k}b}aRK̸S+{;zv >.W\ \ɳ5fY|WkEzu'VH&b+|z7+Un:YKr޸RS_R/JZ]vtVQ7eyyovUoWzJ [սt>ifM:iq[oZY3 UsOhP+fA>sSO+əj`^s{KHxsyWmեĶNf]U?;ItTzhT :v3c5/F,tw +UM}Vߜv`v\Dn7r~$UW,\g>zNӅ k,r-É-\tۣL'-^8Ů;q@Wx;"%IWzGg<ѩw^PsOŷY(<ͿP벃똄n/nøKy3:7~4_|zPۆ0|eMg~uVÕ_ +:rJ9# l .'ˆnS3>,k+Qb@jqbNw}LY>>z~|o}Xf\2yȸH*b[bf+s>ԍG[Ν&YzʟyOzptDUGf3oJbƩ&jr'9i~)-ZaWÎkoz{?BO]X"?D]2v1󧙷-:,zQLQ7ˏ>:wkDoܙHIf'=W3]Xd/>ɜa=#weeaߛ$ +9E>ae|SѦkon ipNVrSاEd羇,./q<.rԮOe#;TޖO8{3%6kIJ̞&]Px);׉ /0C`5ϙL~@fޟ[+.LɏG_'_ѶMKU +,.4T[,t:pd"~5m{seFOuwǮGܵ3_Jf;j-ޙE(..ٲ6jW]߼[qA˿W<9H5QZCV%Ox~2:'_~x)ӗ/OҜnefe)OPdl-7O`[r>;v|JS[o9qbKNncz1b$nܪ͏;<ǥHޚƢloY3LOv"Ɨ{cueR2,κ-pdLɍ&::Muyp EHox_҉:yxz_,:漰Roro8ٳڱlc# ?9>qt/|;̰W.~Qɤ%>n<,Պ̨U~̓]=Wct6\伱37l4?Mt=njwW2Pc"_mUٹYL=Go3HOΠhs=UW`HPp\_չ_^xo˾{ +D\O|f_/rޯ|YНS]9)ΰ;9aqbJV&G.uu2c_}Bkgw{4Q^+-u`瘟jHqΌXkT84#y\=[嬩s=M|_O%s{6 +oHh SVp[mSmLǶlE-e8:F|䐳$aVl}۷A҉lz1"gM[>2zLwˍ0G.ފX.},p5&sgͨ0^U4keMl\e*"? g?d_E(O T#W6uƲT9rgLSe,k&a_ $Xt+{gY1|XqF7VY\-n':q\YҔg6JV2"|̲-S_Kn e!z4vRk]wUlcc?$^AMBe5{~i|&ɿ^^ٰ˅O>HO+o_߻u7]gO$XxIyoĭNr ޖJ&i w[{ӗ)cIw+\)[rY#Mobbɷ?|2K|XYɠ+W}/.wߕ9+unָjCSY53̌ʔN +;\Q={[O<. Zz$ՇqǏ˘ofz~ʊ0ƔGKvܚh=Jbsr]VO"r<|~GBCc Ӛ]7147XeȳO|<iĘ۶'.f?8#Yxe}J6/>l ׋HK]EouKffhpx|78ez?ޒ3E/\RreԫSE~[/Ei};u{кMzB^ckkT*/xX-q7l<=L{ȓ6999ժ9o@ _KmAGJo('쳵Im1;' +Qҫإ0!%~SH^wwx+w޹y'M/mfɮy_uarճW^b=U{f$9^]W +Eozl&}dbn3KV-ophZK Tm2ח݂]A?zs0dd?qaSu<ݸdSi:ǎ~>dEio/MD+\t2Ti5.k_2eB۰^ jj[BLEYiۉ{~h]Y.A#`L|ݬSv#ܾb6 =_*9{OvP/:YuƒNV?V=SBkT.ήV$$*mݲe&gJǽRa{/TԺbצ_Zs_\gԍŬW$y EOX\r;\5< %V8nhʹ;IDORw֧kS͛n{qD-~xQ*soͰtDIxα=Vlk'|hzb+,[g)1S[7>枫ܚy;=qXSP܌UE~\ڳ?ym9M.~;Kb'S|wCKײT靺濶Lw, +4şwu/E7t={&f3s_l^nCSy|ږ})Ys.O3yJ +c..q15"Ry4NL>iw{ZFa~+Ry.MIZ9 Kef^OFvY[rfܐ0yMJ箸EV>Pa-S}lGM׼vx@{9ՠ>im^.:~^dMN}\~wG]'_ͽX;~5 bK+ں[:0x{ex=eW~Zΰ5Flk|2lΡ] +vw]\xۚ<3ޥEg\dtĶiA׏+%&Wܕ[O{ʪ"|/x4fEK wl?gys͓ta2Nu_Ӽ)-e)ds2ٿ +9m*ZTa/g-op4C ްqurC n֙4q[oִ/vua |oӾC{=wȺg&jY/,D}!uߢHAۗ|$xVrpIK~Zd+q?L_|&şZwwu$U4-aY9b^!?8+L[bYXgk :HI2ќV2bM:)gVzO[z^?5/3O%$oVm+YgZi͜.lxy-=t*%ԅJ[s<ʐt+z?޼tao=}ӻճ znL? )۟}{uod!<޺mX|q)3䱇Je+"\w썂_9;8=;>i%5A.=ix~xGd%:_qxg|'EZjKL?+Ç ~nነ[ɭm;_I)olzZTQ{[rXE˙ \]f@p_א4lc]Dx?՝jRHx~Ԝd'n[irirάyF*]WZ?6nͻJ)([KBj+Gꌦ &|rpVm*>atWGNoXu3_*r\Erz3ῳŝ(=7l}Y9Fs9X5Z"csThE g +Ǩ]1<'/չ幚\V[#wDjp3RnQ~AGxx.oPy7iK +3FA[kOH,nK8o9?kW?ZgK[1uQQvPNϭO"RP ,eJ0c^7l mv]ݗ};iG"h9zC qvNw}~])Ҵ]5USA]uz}{[Uk{%_5S[l6bpبY/\KϳRfa +Qx]QNs[(؅|yn}T Y֫?,:˝>^h?v\-{vrxvŁ`oԶeY@Z֣;[O^Fp1 +ib׭ȞR6 ߇un٫nl7˥{g&{l›c5f~Vڲe?I %M=Pc}mdlϧd0{ҚsCtNie[#2Vom:!.eU371 s ~>OqT`)xr&z}mm4ه7忉ve滊V=%ohu6aQߋ;2x'2UIgߚ=<D;w]s{˳Q]闛6;wyZZVw/yWX6sŽf'/_Um5+y!w,:ޡIϳlaݨt/vVK>Z[T|-qc~9JvMLECj_wyR)K}'rKU%"uɗ +[T_!+&/Uo?f<*=k(Nz4sWlx[.z`QkwKOkowR7^ Ao7==ܩkI~E׬X3+Wi<7h*uc枔cHC$sOy!É_ݟ~ 5܌ "R{z_8y BSH{Y8'Sֹ1i?no晇gv~jH_fx|şĄ a.7u5)YY.88ny,ݓ3آ%l(rVA} hެ/z)˶} +l+X*5{Ꞓ{D:*_$f_VpE5ӞTQPqUqy+im/!IGf +%κ%e{H9K<ߞ|%zaOw e }p͓V_+=bq,{)>mJK'k)~ʕ;zz0IODw67YϟzsyUJW]rL Nf4wۧ*#(DIub<݋Y}PeSԏΔG~[sqV7gm~c,ٲϙ*s +G/y۶9e7fW Lj[:)7egK1_wˤ~ë|(~ή??Ybꗝaqq߭|zM{.Iȴjŭ4˘}95G˯^ȆVSzðc>3ow1gc%Ô3kz_Q2m53k21qihX';G7xKu,0 Y;yjbly;S+-k>sco?. +31לgw|;ԗt~O"?g8=uƽ?o]9Z W^=?+vH6K]`a]ANϝ&]++N>n(yo&ak9+y|OTWyWIY:Á5+հOG' s.s\mnu+?qQ3߭]s笗zZprl5.n}`)?MU=(mj鎶i4/z^nu +5/ ~"0w@`֣*p/N8a&kI[mQsecN_ I.gl}CSI̯A^hgU'W|ur¦2ٶ5; w,We/}+Z]ҞEJrX7|ٟ[^QjF]4Ouu£'&Ǯ̀Z/&~L\1=y}9mͩuܱJᜆԛMO*x֕9$fj\mSlk mQݛj[&`?;nE%J7舘UzcOoE*i7|^,QˊيsbP=6UVpr]e(ڻ^Qrˌ>Mfn Ѫψ%ާcOUR{yӣ9\fmKjZؐ`W{43E7ZҍO~Jlτw틯_{M^m,K>pc{_ASs?݌xS{t膵۶%bT@8Nv?6]|sn[=n/=]9v-clTx>GTkSo^ ՞ߞEvcvg0W7v~ :/vOŧW +n8_Ž7֗wcf%кwp=6Nh#u32y) +Qbh,*< XZO}ѯcU7^8էq2z >Z1ׄT=TSk_gZ&cxr+!i;wʗݹ%+IiE@Uny6:E]v.Uo~4~]Z+rnf B;t. $|=6qocͻ oJtwsy+-o[Pz4Eߋ_xEԭczZ=Pd%ğrjJdǼNE/%<%4Mo}ߦ?:nݭI ;I9StEg#dĔ )"᣿z8WW$H-gfZ{*&;z$JU^?ۖǯvtL]k]7qʥs6>6/V\kUby^}(~K }8gY.g?8D~K;Y :i8_[kG- +6x~R̼ ugU玘ޑ{*^iDBK=Ykw'G*tg<zWDw5#8.=۩dl_G}[;NU麫]&gVuyB'E.KxB?qbĵ_VuWT\Zm%'pC}TI/.;ꞷrEU|t>`fZS&}DS&Jf}in犪 _]5I-?MN=!zk)o8<ݤ?rsOZ*8&NnXΝ\[Zzܘ8ol[Oq_!s~ӴmFv3MyZrs{ʾ& +i2/Lc_|B}II'7xf򬝯WuHI6VUnt/.`y8ڿ,RHtyEFE.<˟ ߪl%=_n\7EN0ؗ/ ,S<5XO\(;cMZfg<0a㰠p+ Ek5L2SQBN~"aS\O($1Gs7;?H>o[i&yx{7ߨ5,+yɣ++wgWKm%f[/WA-w|n]![w4Vg g5GOGw$ +-Niݏ,(t^SRlyKnb߽SS]6|`OQ]#kt +,ʕѭH? +XG+&=o|hTua%.3Z_lg.wשQn;V2yH1OdΟxR_ kxٖ3޿|x._fnؾ5'^w˄ vKXx-v-jݻ?=b>VV=c^hM雾`Cy+fcfRZ`{qoyU jOZ߰e~=mb(XQcojU,R!"7ML5z뚋M]/~j3فB\K6l}*]r[a/_ :yeӺw>4׼v,yW'mLN_[~Tw aBęvY\`cճ5{m^*iQxiӇ׬0y*F~_̾8c/GЋKO'΀3JL5%>Zʐ'fs7x]Q1|@/{DM[!ɒ_*^-|㟧kZz9d̬6(4XXsaw9MvpȢq_U1$lKJ7u_wgo3s_ ً”31FtUiYC=~ͮ՜se2/veOy q Y} ~.n B go\}q| +R^h܋ ?ا}-oX]xfzlggկo{v +:Zc3]8bSNf+|n[΍J;QyH偢FB*% LfxrFnB9 n<X%no# +}v-ݒ唌?ڮҲ<7k)[}C6=Jz\uo8SJ%{l9p!"M?< ~oْ?르8=2k-K7;v`U79,ilϺ3^k}Kb-+Vp- 'Eλ5䏍¹MwwˮM2m?;ͷ}%s+"TUN/WVgxɆ 5Y/y.?7i魖9oCgO۫(xhXgywg4TIi+X%SE.ə/-Ve1W՟z?sܻef)bD&Yھ ۩O-Ƚ"}ً_ ?ڵmeS{F]ޜLxlPqĺVm1.S* +ؾjᦢOuNXsɖ*9;<îzs~k12 %*VK\휼]+ܹOP떎o^[f[v]v[@^q|'itBv(;*[9 *nz<S\SD<޲qF8֛_wHPOc\ 8~a*S eMv`yc&Rx?*Sm/X,٧Y?ӧM V15~5jWjFb?%g^f|l䓪"lzoAff٪[+kTSi_b17PfoMy$8m12S e|Vy%{-W|fm-ʽ厚)WA w?TRPCD1lf;kL8|?_[6s"?=Noo}}&o+%7鉬ݫujՍZr{;g6rܽs\y7/iv폌UrXYVaƒ;.0^YZ^x{|s=oj͘bw]YWsŭϭ?#TdL+Oa +v~Ucov57mBæ{ o59x9󾱤^o"hmW| <4![~9[sBs۹kOng;?s=? [{[oGoڒ;I^ZoO7VS67>a,kpefC+y]XP;vB}MGTv^**>+|Qm)޳]zˢ%*K==>*ϖ(ĽCkK;rcUK wErnӛr2H:7/dȨ&eξQ}~m{LÑ<V<-/3]9N|ohj>{Zx 5yϬJz|?kbE,<NoV}1;5u_bz"O?˵nkzf/;,:qo+~o2-a#5fΪM,v|ȕLᲠӽ;3"sg^T߱?'Oi>29OD^KMV MrܞŦL΃:_S}FPes.1k {XTJz{~{GĚu! +Mg= EN?.1nyف__k_A&zNv3ZW}oMũ٣R?4MpdCX={[r7V迖fX_.Ӡ@Zӧ+-% ^'' X\#fA۝+=~^$r<'C͉]cI:$LT ~7F8C'VW.4c4az]L)ݹނk3~Ypʯ  s<7}Ql*fǿd΢ye5s<:cY"֙lI=x1R -۽SoZ}v? ޽ݼu}_?,|ar-7ݿTV}u:?u^szۈkO9e_$geYkqwkQ;V5oiI\S9+U_U p77Vm;z୔w™؅WՇIZri[,pygF, /t8_oRj[]@n{4X}״#Kr`J{\`X.|*Ν*{&dN6)J;[~eyVm{3S<w~n{P s?>hϪhP+_cJ[^%靮g]5IbI~qacOyyE޵5=ǓO;ƭzvyc=3Od0%tbd|2GiK_-dhIχ$PY09ostdΒ K$jf'}l5gm2WwMgkklx0)(l\FNJOR<v ,*;]LL4&x}DlҢvIYoͬobwOޯR7^0b6My#/`-߀f2f6Վ7[E'-;@2; % SwYdY^֧M*7uuNJGέUbw}Nh7fK>f̰kEnuv/mq૳:AsڶSIG(^XXũVn鬟hhY|cJõV83co)ݯx9k$ޅ]l ,عPj]qg՚N-5̡vŮBg-?:+J<󀐇nwz%Wzg˯CiROۇY\O4&5̪%C)_X\rO"O.v.>P2m݆OS0r,S1 .';757Wb~fK6o.M|dqRoo*˿3_S&su_.;χ' 0:cLk)EcϮsi]#j8 +ЦtɁk׼N1ykәʬ :]?4_"/lصS#&ey2uOӮk^%Iy͜qhm=U2/ + N95bSoߙ,7rso_=뮩^[j]cӌ=IM>9*_]:=bǧr~>SH?rߢ~KvHi1'45x:o(L/>~(pv~tݤ? *R]Ƙ2fE, ֶmaܓsOuΫ :6h+,Y՛Ϟd5K(OײXxFhKȩݩh]!>as:_:{[tѱz1jaf4]E sW\q + ]nc>ZdK]c6oKCVYX9beZ+zي0?+*U2#[.ߒ 0)ًs-LƅN阙iN8Gz6~ q۷_#EZE{KN+1߄c +Ef-gԃ&9% @S۩<.Ho˟+3<40bٲIeOSLKEZy~1 +ݼŷ؟*X&17Lܮc ub;MLiJd\Ȧ5~a:VoxTA1#OM E!?j/\]VmÏɹVV7mT{W3;jht Sw2q~_y*R^&ǶRzsYF~~CGN^!>Ea2G+_9׀/ i mпZ9W*,AͮdPϤ/v˯˶jX})^aFHهe7 -y3/|rjyv2:_Y|vC؇?JJ=Ūη;?/K7oTVmJu|9zC=ym +?lݮ6wBdcze| +l/J=]j`n_-27ۤ=+~u A1?,Ixg%9+TySjprv!Ǐxң7jSeNgS.I\+qһzxg%WmN~kz?=SZpbf6sŕSU 9;2dE&nW\(8˵|"*7ϲXLxmN}:VKg{Utf~>go컆Ň' +; 6Ulrg}t{N=byߧμJ$ww}+*M.ҠSŢ;_-J;tA%G֛o%Zv}-Lg'=;ۺ".4gvo[׵2}v٪{ ˳+}'; ~uջ w1]sEJ𞰬ri_hu&+Vy:힙NxV'RGx +gG.ZUu;5n ?/ᬌHۼWYߒ|Zt#cDwP>iUGf鴯rlEh\#ܚm}o_=xNF^× +5i0ZMfHrKY 7mf*S0:KV_sI{]'&~q_ˮ5c-0WƏx"o9sZ=uuʽ(w_Ϝfr[}ۑṟzb5վ=חK51/Hȶm)tϙksTdH|Zn$Iw t|]U:3;w3^>ٳǀ9kk'RF|/'G8ݟZmDw?\){7U⎆;Yo%?0s96^d?W褔⃥!3S>h]yqS?N+K1=9WSb>9O˨,u'J$o>X+f*;zqyvϯzxP[fvKr%pGM4)bTEKn5^tƕJkK^T)8:MB>1o Ӵcy`ܰ$ݿ~UwǦ3~㧊ڞ?+Rٳm[4׼G7[p1/ݿ* +1"rU +ߛ)|)Ä=ֳftnm)` + q4_~KbѱV]gxȯcEjͿ}^VLG#qs>x\˴;wΗ|?CT]ͷtx/.9^\ ۗ+v$=LԦ+~?O%ءICV2W25O2Oeb]9C}5ƍ_QR~ƾ\%lklzڵІ}FzzZ?uZyn^!n2O,|˓Żf=fwϥŅ >T$y}ђRFoΞ@bf-OO*#iմ_R'8euv!e_5&ܛ3ƚee>e[2:#I3늼T<+c54_Jl?eo=f\(x6Uj"޿? 5.=;5Zy +%/~&Ιs\M oJ'#|Y䙓׀1)^qGRwL+\w|DZCJR& mG}\NqKT(2͓q~I[WixRݿU;sԴ Gq)~K*^-swef*7U Eԝ鸣atн'G"U }Ö--×W_뱕ZϜ +|uw5k(5FvW&|W%$árt_QD3|7JM|ΘaRע=粥se.[5nl?޶33\\ǧUSDet a᭿|3vku?Haڝ˟J-)X^_|VJwS7u_ZԻ^TDd]·:Ou[`QY_ ֳ>D,ݡOB&=~g=8k Cĥ=Q%+il*8iS"]a=ʲI9~1G/T7zko*cD]*и)Q'VK{/u:z'guΊ”iuKrM:'w:wIbOfmW:̛k[W5,{BHJ1fй;z,ݭV'*ۂ~{®\Q&yYYk- ._B&s*p?FUߋ9=SfjmF[Yx>n?kOdjtwKWvBj΢Y:Hef>aUWQ˲-}i-c1 ՚k_W̻tZ+^Otqw֊pw[Oh_wĞ;،4Laө=k޸jpѺeJR~uϿrY#2> Qp^ykCW3|*w5-([]{?ôrN5'/1z>'$(ʪ7;){Ľ~H^w܊i"vu;W$޾N0o[7y_Y!KjYz3,3E^73+y/wPJ᜜h5&UD\S,[ɜh=uG)ǐ7;r#X|JtųX[zlxEݫfݺp5Nr?/?h]_6ȩ&?z1b"9鎫^/1ZXjBȫFբr2(8W%L~Xe]eSF}9W=?qJml+.+g-p|'&S(y)*fo_mgޟZtgv;>1oMS۹埢 D[wrGӯL5v=u'-.Ov¼Kwǟ9mfĄu 4.lQgt\]~sDyPBϧb)qnܛ^mt4 2P1ZQe}i0c_O][sDku +I ~cuٲABfAwBw3by].(@Wp5C<]o +Rbk~;fMUۂT.q4M-TpI)3y>.=+)+z]47K0k-ӟReؕ>}ypݙ_m d,Vk}9vik}:&h(ϯW7 ;?cC֚>yaQlqrY_&7:f»O%nߞȐtB"i);/[c.ۦᳲT򲿘^r9~{^D-Py|z+kw~6FL|Jl[J_Rw'n 3`|{!4x8KȬ>z| +В5Kr%^xqiio撛=FoÒDM>+/=Zs=O|xT{j㵴[ra{:juRΗ,_ڳ/,4Wemn*!{LsW .+|Bݗ_ cmj̏˨>!ϙgzsΜ!v~\[YiO|DxuV/iuMUxC^ZY嗧8M\$ߐtlO"xN X9}-I1{hf k$ݴwU77Y|i53zAW< v 9tʗ[T'/*$iK6~޿KuoRwd-.g|~j3k+#\"=3/&gƳޭfxH]_#y|Ͻ-,nW_j3l`VgSɗE;uu?8`KOޠ$$::i>gtaG`_V1{|]oANݻd}gml|;AT^t϶=Dw`Jw?ݩpuUY3olQNŎ$sӛ]\<o0Zo4q:=Nѵqe ?r^ľ~=J i#^zOw^wK-YZۢ21l\k@J)ĞɻpϑY b&97-׺x,nS~zW~R}y Vf>j֏_Rkbqt֙&fg{,}W6点>>t|\Ϣ# D6'< y.v +^ j5{35@ͧ;-^8%n,P??Vwʗ8V~ׇ> \p2+yəl9sy?";ݙͅf_P2[FCJ -<]>g$~ݮ#z:~OkBؾ9;uWwuh ҷ_=qVٽ|O=mS_Zݵ2`tDCk)߅,d]O6NZ{I(QUWO^o }\ڔgG;YbIV3v.'~6dMᘛhZM nzSeofp{5\1!Rmȶb:U}׾OV~.UxE['{b~xJOlԫ)zbٻb~ݛY0nۜ97_ʯ^xMCX_uĪ]nr`u;ή+yiC9ceEVL(y-f+aQK9kf\TPCf@VK޸k +,zk}NIG[>?bO)h^_yZ랿8yS8a._׹;k9X J'wz?;R[c wm:*|߯j%S'|oœ3Wb2>乸_6]o+eOn Oi5_OI:rƏZwJ=~8u(z9,vu]iח)ZsG{v(%f8!{~~C՞WrN2<{^ӣtgK]JکS^mwVő~lF|a'E]ş;t{ؾ1[$0gz _ndy_;}o2ő/4!-Y{芻" +mcڞ)4W b[ީjӕEK#n\Gyg[k+nn1M9/=mJW=*]"yv^Y5Jd6gN3{ٵ{]uͽ1b}Z3ۖ\fTtɴL?XUcS\yqԙ?4r%B&sJzj 7L~|l⟥'|'ٳKӗjWv 3tQw^wf_Xv&"@&ɜ<̖nڧFKJ}JϯOyRϪP+ꪫ´b}>]t{ hZ'}*QZT*Qg|nt᫊ ]W^4)Uo,SgJk* qW~F -tc$m`g%ˤ9Z.ynZn[7eo_媣ОAgݜ0m]{v$h`GA䡊3IW|7[w^KVF {>#],'*XdRE$Lcf!N꬞mSjn%(T'<:U)OJnHw(6?:x[03[}]%˾ސOܼ_rq5?);;Y$zՊGrlIyE{.^\~|3J)` 8뭼tcMeM]~Q|@r]rR:τ$8ؗ~#];4gEn*SܴޢU'f,T=+>-*[= +SO4dq|~bGwKzJm/TcdiUlۖ|Q316YǮs=G|jc/6*ef_ΔN9gy4b:Ñ/V/>lz'jۉK.]/}KC4ܟ2zyJ1c~/Eӛ_̹z̗ݒY,)־ys+ ]̙:XSÀqVwcŷ)7̘ӕzm[6˷)~b뜇G6>f}Ƽ^~7KA+o5[aO_o\+rEY>|>˩Y,96\){G좩ʽݢq'݌76񶗗ސt,{*wl}O$ywց=M\oӍc]hFo8,wJ{>ݱ&MI>_鲯.^eNkǒ?6`}dxzMi؊5#%֘;ECB9S'ޒ?1y}Eky"'8;u6Sm{rm-gmϫ3&y"޾.2C~X +N5>oPɜoUjzկumԪ2o^23j˛gA_7gY?1=%ꏯ8nk]~\}gBs5{ikl]}O0.jp0TYTZ)fˎ]]g' .)X4c6 +yo`,2xNOgvwEb7-ץj;-.rP=XZY<_ +;:Ŷl)^2؆YJds,3eԲmG|}ƥ"pJ0*N@Kd5ϣ-g=lho߲t)z)jJVy򒽭u?\u*!TǛA1~Jg.Xr3zҵ>s/x~F@c_AwM8gSZYyk:__%'!"p'>q< yz; Ow Zs5Y/։ R&JHX5-A$i_qC4SKωe~胊Uk{%&ʝ +=v\UUY/OIW_fLTG_M{F;a<-sWi K^7)zf;˖^.~\>bG!F/třݏV`6Ye?$<]T~-;wop&Ԣy4\ǂ}Kj ղOIr-{[9|9af66Q PLfTwvQOS }xϻs~o|)13<=,ݏbOoasd8OvSxͷ}vwK}$z.gOk3OK!=ҏB݄$oy-{=F;\(B3?ȈPoT hs6qM')8ThI:%>%MR>8`]Mqt6.l~^E2Vw+uLW~vps;b^yVհvZbQʴcl3EX*?lsgU糿^g ][ݖ}}w>ϊ31/3~uō_\O"~㕧*9&qpx/U!tɓ‡~q[ д,%Pb ?96YĦA̩Va7Mluwk}O;궚>^6n#m5|=ueBvpT4]}l"mYb˜Oa.6[% b4{H|gSC_x0N}Zㆴn:U-&K~hY]ct!Ê[;my{Mtgi!﷗į=ۤaN?5Yȑg}\I^D̶K~VxfJEwr?K-q{oEۓfkzUzNGp _ײ;m1EO\͕|Nms9omegQGǿ9y9{+f(W:mSO4g.֩k/>{MQĂ{~xktR[?oE`n4S~eՀ;_01dm*<*7+"-qFw{\;~U}NZ7ሯ,Eomٳ=ڰ[Xrά#Pk{"w%V?=i{ϧ9Km,o 7>MgWh媻gzlYO7t r?tNAO=)cm9=;| om!NjWyLը/.dβxٿ'(t_ۑ Kcv-əsZYިߟe褧S$+so;>i7=~P`oƏ{UhcIT +&Ks Ŕd3Θ:SSqmچng<^jq?[;# S9$u' vw R7?9\qӐy1[,\5]wuфkz!T\y`z܊BRKk>09߄2?EIlb{^My9*N].; v˲fz5)F'k"g '+_"Mu2圇jL8nTEKV4.S|W^{ʊRэW3u J'mKnye~KIby3CKD+CԘ+;aʮBkNԞ韢cέ|R+^wA3so>3Q-:fG>\+zcct8b*|4}jժs?WνSR= g0nf i>5Mx+36pujX0, =j,[(ퟘͭbb hͨ/d^_?wScx 1zjM_lM +{/\q:熾j:mX;iN(~|MKJ^NtM.pk7Ӧ-_m=BK[u熀3,)*ҙFvE;vu2%/ =bzuMg]eO]y!?wכ+86=nU{rl6qǫM2 6>1ws箱97^>9~g k~xξRnOvC?/R4#2Uש5a In}G[By(})thDSoޛIa36.?QKm˩eZK49u_ˣoOw\εϺiJ7&)(s`[cX(*q'޼ೡ+e"z xs.򫹦Iwbܧ+<׶+#2xk󍧉-0#{Zɇ(Ͷ^Ru3ݭ)2O>{?,q7Z"r>'eK7WnĚ~f֓#} vRdl5Y滞Į.3s$h],<%qq'_ \p۸Zu_ľ?x+59k}xXoio#ou}f=ȹ&W&/'3NV>7ڐi5V؛ʍ+e4n+q[݆Y+Hꩫ}>e/p[ nvzQNS|8ʸyzsfq*nQKؒ&M=#:7~Z[ +%l;?xuvg۰*u7bWkxxFSqΑ+&O^ !G7=]{LliSokhzlŞ֕nim7ųFo鼤@ΆwBrӔ]+ 2N\\Yzh?_n?R85Ϭ&b?^N` +;h^fu´oxu\SYɹ6{ۿM?!a}vu'~5Q$_)~io}4Ɔ9缄i:i~KU_{kEso:9d\^#/W4|㫂{aL7x]Y|󫗼nno]ޙh&7._˺;6汛2s9WƽR҉SDX>%Ee j +Jan.4ϝՊnF5F g9?2atDwTbgh)%*Jv<.ʏܭ] 桾abZd+UN-|ʟ"-νz½uu"'?Kh.ЮcEJ6fJ>+GO̬UIi~I:SB,^p聥 kٹ_>᷍jǸ )[Sbѣ"5|,?}ZݼiLnC~K6*+ga0ר}HI鑕6o74w;pJ|W|rǶYS>g_Dsrk2{T&IዙrvEB`ijulT5?ɩ޻qMC7b]ȥgϗj -gWʗIpqt=yWVw;̨y-%C4THC|ҩl$رλ;㶸OV.W=o˾퍎N~(|5癋|˸>pX)b{_ﰿ̡7~iRLV`Aҋ,G*o_ND%K_Ů9KN\m߹g_rl0nz䲏lGMA{Q| +ׯPv{+wƇJ/2)XZ`ivTcǹ3 3^JtY_Vs4Lk̵ k#b]%["Ε0yeXٸ,TY35\f9 iScSjN͒[{|9“f9Ɯ-QV;nmYu<%v#3&s$O/TH\$mpՑgfoWgxyg5bs/(^sv_F8vo_ߌ|EqΑcɝd`K? ,D/Vr1 Jo ߕjz|GY4u7ff\06$1wcLW/3k_ո7H.:Se,y +yg}U[FZͫJGgq}}i3Sr|pPs"BY 1poibѩKŜ+ggJ ucyDg>-JpzfT +^kk RLJ>ט_ ̋W{:m]'C3$8}E_Tln?O^w}5Կ\{f5_=];䞩9y.{OV?ldUt&G髭G LZ~ѽr'9,]xb_>[yٽi~,ҵZn5]Jb޲S_ Yfr{XN74o%ٗnM\l´+g6]8cWGam;u 9_i>!@&Y֓/=UQbsdLP~y '%gO?({ ~d;^*WYNe k:?ݥŤuSvCG= k#xjql=;˟^\yL,%~_ypy˚f*4s{n<[󥛧䇽63*`f‚' +N^gx5f/3~*_nr\J)gܲ+Vu4?]!=nڤǯe̞<}{}heFe6NxSy<*.n-j{,",rzǎ}$ҥ6~Vavվ:^ˏ7e}8Ov˼z]4ۅ:WkwNqe178.le]?M^RzkũwUo\R;^)bƳ_/+aq`?ҿZ,jd5/5|{BB)jfR{e6oY3~hUkg?<,qԌ=rc!w ?{z'!rJ)mq[onoȸoIcSft곰۟[}xCnoKՑ=al{SNLcu^Wd˛Ѿ;3]_^顑:K_k~yڌ77WytOV8-+~G-pGٽ7>w#k*;"/0f{T6Pe7i'ZkP5vi9.o$d` +_ ;ڲ,K1\+[v }QJP-tLͱKyYtdWaxCbTwxsؙ%i<3t̿w])<W޵eL/61 +&pr}=a -]GimgDTFF< 7߿nhL[=nۄu1yhVNg}#cnIaoq!W{7BK_&LgZy6euD<7,JMixG󓧾{grzB&1]f>}m4^䨘k@k fκ6>I+! 7Rᨣ,3%Sxb8!XY g7oȿXJ(p|?Y;Dxn:4qѽs<>)_A?CSv|_yY*Ʒmw lA-KwI5}=iFnqfd~b^=85 [߶.9h^zr(م7:dcqU@Mƛ|nz}ugx.CxrSt٥P.k?x`Q΄aiCl'EwܿwǽRgˎw1_y +yq 3_pYLoDU%usZ_j-$Vk30Y,f]ft>s Ll)K..1zŴU֚Nw:tt8_C ')~Ϸ0;jz=ܻh,-߫>WdfԹ:um٢#6wW5b7<,ltwK?sT_9A fxϨ;Rw9t3폺}wFշY 0Z/)vыyuM׎tEcfȻީeOurR)S{UyʙPCG Gǯt.27|4n |U)4OU;zk,=WG%<3(^pNמE_Uӕθ$hso?mvYB)EyN{i?[,({4'q͋?^0{Ni/sk߱ENd%q5KcIxY`c~^ >}/*sxz.\c0 k-5}T+?<)|=͢Al-\CW)*VKM=־8bCߺy:eЛ ??[ڦlEG1|oLJW:9ܽV%WK-P/*;(`$[%W3gUsfBTߞ\wKxlejb~*bq|#Biʘk~9]x\' j^Nh-9LwOC2o*Te4̞8s'| +Bh,k_V3U&좥+p˾~7|]ԉv>ݚ0dRZ9J>z/.[ʠu^T^luTؙ,5|N3S1mE .M.Uy+_}"?co}建sW{.sY۩?skN|B~dYnBröFK=b),qź?8|dk==XF [jha+$g!gs<z Z٤nuv7CG`]iUlBcNZ_{mQLAsW+|?ו>|돠[[L+V&$ +1Thg\tJE.|}uY^ 'THI7^wBuHf1 +e)iP=s2 L艱=rNw._mCmI-7W~Ci+)yG~!m들l2pι~|De T۳X,y/ϟ|n+oϋWtcWڙp5^uIItxy+3w6jn[sČWBB򕗿Ÿ\x'mk޶:ެg_HK]28S1vuO)I>3H?>܉-a-I\ZI°Rцy.[) R_r.}#MgzVPͅ k=iJW)k/^'u`1g|~?6{`vpPw+[e|^N'ɾ&YР守 /"lOdœDwl1Ѳ!(yiG3V4˫b.9Agi57zy$O +=hAˏxy/ϽodǧZ5\5g9{rC~E8M\VܱY7δcj ,|c쵾חduZ1%+Sr-Smg/TOY/Dxóo}pҗfvizpº7/loNsџ:*v6u*%e4yWYUn2e56[L(1[,#%咼]M㼒Q}1jԝ,ĻwTϘkUrsBIXb\:[2fǦH9F)ێV5=fwݬ|a 1O?s*^^̪*?osupWǥ̫.vN~\5EA{5"O9(D9(+=~Db=5P`cƉ܆|ㄞu$gZB!gr:V~΍f0=;V fs*Z{߾5v+xjN>YKIU)_o>8xn 銿M.0l"3ydWsqNBwBOڨ~"AsIXUeaĈ~mzyT@K8KO;c~i՗ߞrLcu4z֋s˕ ~ݹI=FOK#Yxs̙;\SYãuܵN }7qׯuYx?s;[\íU,e_nڒs˕ cYh}y<\eu@^eQIk>|/?z.w_/fq~V?_{N_ 9ډ%!{6܌zaQo'qxѫ\!%{Yma.w3Yr?e͢-kJj^ײ=:k[?EyN~ڷhdقA[ϼjo$-j +A]̔/,Ygٶ,ߵ*?_*3ݷ~-dؿ'%gfJpV 8z%O"SeΫ~qI X={ŮǝV.͛>>-g/FWKG vf׼Xcn.1Ql%w ?Ѽ0E3yQ_v=3N?D6dĴ)n>5y MSxtiiËOg~ZUUg_c ;W(5N%Z qYSx5뺓ɼ3ɠDU:v~;§X_^/27ݲ*^>=;=b~cLD@+ 56=?^jtʌf_Y_OZ_Y7Sg{a?k9W=rl7 僦ϛ`yc+J]zg}3otEH9D'*yj }Ymؒeם퉛QUَlBqhN֨dɩ7ys-=85Tg:.mWgLj2kD=^W]tֳ3)\29Gʘsɑd1mۧ䬵i~ %*;NT-zXZBBAe s3_:Uﮇf{e⣽EwUY$jr诵[2PPƒ~9E^Ix9˲m6Ke_t.jo cvrN 䟟ac׿?&TiS˭&bJ>wI)H68I$z1{?YFaQwsgC֚Zk*vs~2kFҊ?nY(p֎ů J8< S%$=LCɭ<흾˼w9כeJ?U?6kY{T}cR"lYbܵ?8f*b*nqK5ߥKۣV;ݤ6vj\w~? >*!sr1Z3=4'ۢQ˹m\z2%떟v[U?˾Ǝ/$l{)Qe?=u{&u7ÖRޮw;^PyK3Ԯ]|'ꅳV/z'o|)wp^?Oz3=9fYWw'{+2|Qx<ɪcR͌ ܘsnSO‚x4Hl^~q^֔jɻb'W-x?aۊIoh>²tOA32*nơ>le5P޲*qe [%ص*}V@pƅL%ߖs3=ҳgK}7/37kp_љjcZ`mt#K*OmS^<sv2r$I%!<?j3ng?)ke婨ϺgwRŕX4>jafU&EʻG;]s#;N[/weE%^뒅sn$|Tx1qV3 ã9ެ2u@k4e}pu+`<L^zBq{Mrysםۡ[nӵU释>SYD  Ȟf\ޅ zq/;wipxhhux{Wjg|V_G)濛ٹo"s-Wz_t~xnfe~f=T& C;\{A[+MO vbl[Y.㚊 }N/I+!=s>:"ޘ}ce^X}=5-s 毃7 i?{OW]fj/넝'=\qΦ2C}ᑳ|~~k~!y3nl]+x.j_;Y죷j 5bGO8ægUEךU. +tzՍ|nBIR{tǟiV.>Pc]{ZCc͐vj~VLDpUurZ4^♟>L71`a֎L}SpUMߵ7˒jNeJ*ܗ~? XzEr٬m1NӱSSGxn|:kIM +ZKCy;DBuC5\kWnOɛv֛Sޭ{/vÇ};ٜO-r=,{ҵDsF?sy;e +*'?.k䳼69Ƙy*OD.nM$?ИcFFRj1W2ӏ9Ys}1¬+K&i;fmӽo;.qs+BnYso-СߟM@ghxrׄ/~5C&f=|eع +)Y9xF^ײ}ۛreovsX҅K?}_S} M~wZ!\7 G9+scW˟{QڮĨɺg>"a]b_E_m@E>g*"9/)]7:VQvg'Y4LnR^Tl|>~8zn ^,}h&hO1_NbύY]/Ԟboꝰk[,H5pҀ#tfȴ!w+Īmt g?y!+OeAm_>*5i+ZΙdbQ䵼]M[5L_6=mĬQ·?=?]q#ǮˤBTֿ{{O3O[%uep4ٔ}}wYtzZHڥ<Ŵ$ZRW_?]W"+)c#>ƉK.}\q3+Fjnn蓗fnSPm앦z\|=y6mؤ45F)Q' əz~mu5F~Uu(N{ޝ> ZoE^_ՀkgVӹWn/ ]3'ӑrmm/j-RN'3ۏ_uL嗹X,}&VA9JygWgս=JXl-O_t \ueQ68fbG Lyz;pWɯu~V~oQ^\jg0&Dz3^ORXi*rχ%uk:glƖ5ɍ{TOv }3GOOLDUjF՛;8A)c%õ>* LYr5E&.;G=%qߜϋ,>[;#gm{U^<{}i{7.qͩO&{?LKt~xGOpk+B_{wκG/8tfj/g=QL!'qKUEk5nd=v!ًU,sⶬ痸)'/\?P_ԅ[g + ~-QҟϏx`xuu߼2\$/y%fojpu7~Z$,VPynE7o5vg&N{paIUZ6['X2{h/W&ةi%qạ'eczfX㺏1J}v[ 뜈iTK߾?nǑһ*meWsY]t ϔ.KW٬/#|ol|慹[kZbwڻ緶ggOen=v>"[. 1g +1%'=~4컙FSlmּw1:"=+kilQKLI&8=xӹ̱m:-<7I6ޞ08Kyš$v;rԼK~o= e~ޚyNU6M>JXxjy3]"~G;݇*KO,RܝÎ ekp\DNhãsS>csخ~b;]s,^>ܩ#7rμoBv/Z:c0|.v%Ƭ;* !Wv9Tuߗn1pHNxAu>#m+Wq/4eJ|G Lzrg8{&T.6/Ymu}[՟% 88}.m=m``5]b6oE[7ez "BiT XZ|n + 51'uu_> |ikoz6qΫ/Ǵ\Jnz|if/_X%(&>ТR?ŗ-Z}$Kҹ5iC͎# Y$1zZlsl3\ޕVOIs,*=b:?e˲5te^Z+ޭ3nm]:}ߺ_oK&_~_U]ۥOЊ}ɪGj#[ i=_CKn.Y"I}S~=1Uґ/ˬmUOH$&ɘxHiZQ6jՇT8a'LQ|/#o=/$|4Uo"[vpvӊNwҕ]Ia1 o]0)s/_{{vZgl0d[hSv*c(鹷Ӄg>{[粩D]W&9ȧdINKmtvPn_|`b>^=>*ٲud +C>p=tejZ95s./hW"½ hZ7Ѳg9zwy.{{n9m"`E.&*Li*#I߳C8ɮ?$i$\w돾ќwۮ#yG_pp\Kh/71}eG˫p^nيwpJ^ͅeyNSYz]{|Og#zOy+_L `Yǥ V_QkŻY. l =zhM +ӝص\`JOݴnFNىN58ރu#ky,,b-k55\޶C[N_mմյ~d{0Ӡ{Ƅ#8㰸q|'uVq~x,V9:0k^6L\9FT a0Ql1nX _};P'z̢I3JI~qkVwY |5nߕe6M_ yȱUrY'q -oOs9uC@2۷-mRIsnխvsz߻yβ_?ƝxÊ(ĕ^o\XjZ!\&Dy/3rˮp[m%DᷬWPѧ8ov>_ZiXU93l]!`Լ}yQ ecpg\H烾[ls3uYwDMR8sGŸwNc-Kr*Lz`Ͷoo$)?X8Uסbdόų{u=f^ҋH4pj/~%MANuZ[mS[g)i3ql1˘5+ni9~Γj*M+,RQLpA)絙+mc'{ K-iZ^pƍc\ZLr-R$~0| !_9+,2n*Q3eUx~ W߼s sbq#E;̈́ j[|sNf ?/(9 ,<_[nẘYevi})o~E~ES~+-<&˧;?g 2w۷#Us%uɽ򔭟3̀_\NeIEUz]o 1!re=5ѭmrll弣gs̫TuOyFў;Z/Z7mo v]e$/QnyEDsڋcbb;WZR8'yū.ʹݞ='Mw-ϼvzg +s0ޞo6M<*ԟvyK+o~b1Xh"Kmxn /o|Z~Vf |OH{]?w:] -^L\jҭއ3XvGݾҬaEbh$~)7Yʰz_τM>G^57>aW39|}dGāE:3KE(i2[Tp +N-[V.s޷ܴI6~.wNʚAnGyn ?=n={l}vڲC:;m(;DǭB׏fo;׭\drٕ34$~p wIUfTUfX}T] pAbGS}!wN\ Wԕ_ Vت2C˅ + +Tws2;ZSה:i;>:5&o o'7ΟɠYioSuy>&ylEg:Z.8pDJw{s\卧Hxۿh>}WLܟ;Lu?4/Tw~9TlS3θ[o֊G5&.bz|xr;^ZxH :E۞LQXxnKbr>-ʑӷDe +LQxRm_bmo +\ߖ>$7^V\u՝rY; ˟/zb_̲@ti[eW=Rc~^U\.]PU_fΣW;83mHtS7^hZY^EvL +VbnFWt3]{w+'_rzdY\mWO;}cMZ{c53VIVlv]?ώG9fh Mz{VUiInǪ[:#Λ [?X{UG:Ԉ# +͋w~⺋SkyQebi~!.B}^Ymܓ|wA7ū}wf_ZZf-?pKaQu*ML&we('rX#W#sw/;Ϻޤ,LZ_7\Ka-v}}k:&E( <8SGNfLhΦ)p,k߷(+t]f\uEb?Jzė1wM-*zFA75}T`.^5QgԲax/UɇRݏ/(Tu}slVnmM(R~unt`׬ϗ U-!}K3Myg븿c\ wf7WnrpVڮNLn{Pش>"FJ?M_jݥe&;bɲkUrXf3IOMz"4d}enXSެn\J[jO\ʻma~pDcajieZu;m-c?%bGjǓz]uڙ_ +Wr\yG|3o޷>cf-o<|Kl6TȥM?9MiAgL*5X7ߴPS;7U_d& KY+N7aao{wΘ|{;[G^#(ٰW:}84g n[~L%ى /Dʹrv-}' _\]Uum)6j$qFfm3+Jj22 I-Im*'Z调.Ǩqm J<^+6ÂVM+tdpR]iv,IY,0TiF& BaSF7:NcŪάSWg|qt+#⥾V26/(m`Dq/|E_8=ޓs='r@qF'G"Umg%~op{+~o%'''( +<'Kz?L:qd'v?ql% ikU~YZ)awWx[VX|%wî%f_z.I7sOͿ,S歐k-.}*R&_|2EprJwRpoᾷ^tC|{];WlRQ?>.{.-ֻ*a׭e.z} cGwu1ǧy t,""뒣unwf/J*avd ١\&(|ջA5+^ xNsÓ Y{\wȚunಘnK'Zfnr3O-3Xƺ=Z_7,|9Tχ/}5zSƯggUdTŒxtڴlݹu15n^1MJr١9֖[cφ*^qIZxh穛8&I]w7i~֏C?Y0K/(o}ɿ$bsf兲}Lg_l:ꑾ÷XOj|}aT~ީXBSxTZC~&A_g|{t*{mȺqw?ef♚o/o\2zޓ^*M(};DZ#qQ*l7}ɷ?N4:QtW|vTf|?3TNyNJA=OjL߾Hq!d֭\qLgG?횬3Jˌ/Ž,Tnz8P|䒛s*?f^fr~l^^;|˙ Й]/[%'lȶꂷ>w$7whxiͲ7D}wK +󛶢avsӷ0|/)aJ1a ;Kϗvbpw*ڍX e_U\oe +S'k6#'{x{E ~o)^Ydk-6w߶^/ִj/um?5',})JyޭL2FQVRo^;lb[R}wo(矄n&7~OQC̡},Fof=\K-'¿6?aXek;D]3Eװ<} _ǏqӬϼ'Eܬ.YQ],Z?y_iӂ]g\=@n ~b|7wdBX-Ӟ+~aeVİx0gGvJ.W*SVUdNzUəPfE.4(m]ݵ4gYHK{lE25FN;UrRݒy~|ݾҿO?Heosk.⻬gEtfuج-'ыUi'.8Xs41% +?j=no}Iomx:"ä2s' y3Z:.ˋZ ~g(Pe˰_96[s7l1_ۅ[>{JIՠdU>ßT~<@p԰]go^ӕnUfi.5O $/uˆߏ^?kqJ) _s/ \n,ou*&a%O_Nj>;]^w=}/w Km8. e`mKGމ53_>\xvΦ]!- ty|SSU]F)jI|[+'Yi7g]&6UL}+x6׿sD>:-L6r/\)qߦ^S);eaJCDI罿y? [dVpџt(5pV,sUvOw_cٵ6/k+:)KZޜ47<wd̻[mpgjҹ߲/;瞿r&j˳>X}ٜU|gD^ꦭk];p:>㷷dԙ'bh#]ɯY:mf<°(yS>}|sv֟]'1>?E[GojVujZA1G`EkƝi_?rc\}WQ+=8KŎ+> ͿhF~@ZqeW2/(<cv;.H͋I2bQuؕe>2&vڅMnfh=jVʹIQM;=Vsܸ "qr֬WRRZ\ΝKӯsdaV4[g^] J"^Yʨ( l舺|Kü{tt>{wrUFs{3UL +?Rs*EO[-c==!nJc#' +rD(y7+ 扭jLv{]VXsZogsCZVfGʿ3<|J)7*U7 yIٜ=bS>[?;I)aVfTM_JO2s;|q-M-m)7 :qv a[}lg/ir̓wun*Y{w흫{q fs$ޡg+>u.DʾWۮѼmdj݂<do.y,\ɷv91Y1eŴ~KOSls_m6TʥiB KZX}bA\  -&??/:u׿V\ +^y,{vE;LO6'_̳Z!|DϜo+œ],W9=\ұbb!' )WiIb﹬ϡlG<_ױ|um[Xt^ gͰ,Ͷޠa?iȓY)wp8=.9X+%r(Y ^fGI:^D͟5{*h>p#~+9lZN^%Kgܖq2䢠V?|+kʯ{x9>OF^ >dfjGogFVp\g0kZ"kBGv+N|Ꚉt^֕}w>(IϓRkwvں:wxnzѥKJV( Sڱf+Ttmv{\\oO?1A~7oٵlIǣ;5XnZSxG>Nfrg:}W釯6Y|Ok{Rųh1o9C=KlǦ{ rN=Q!4/;i?3%VThMicxG8uvN _b(kĠ?e]BM-n:[yDkEydt2̝ؐ;uA„̩_[{rXs_aM1%ۀg!GB3ld\_PCOr2fl&Z_hM %}uyǝ/tK}~fu~y1ߚAzŖ8tb',)6/9RJx4<!zNR{_.qT6^爈ҏ's,VRWY/Ӻ.N?[;F }i]{va(po*OX-S»?:<.95޾t)(Ҍͻi')]|\=|y/ lpF ϽplD _;\碿q|(uĭ?*,jR빱'z"6ܿ}{Rz5qsSO?;9% .IkKMCtgݟ ݓ(Gdh=x-aY;P[ Onk'T'QXStb'>z8SURjE.NsjtdޕܻvmM2 =Vnhnu {xτpQvw; -b?ϙkÐn~%yRڦxϕ_nuܝp*}|+ɺ&u%Z9\_[+,r&w~zMo}'- {{lQ&oT~oIwx`0WF!\cp;[溬(OOS."w_TJU<[!3Fkg~lȌWdƟ[{v}Β_QM{rCeڷ/Z̫d1noēOc y+eXθrkse|eq zdQDϔ>=+ʢ Kܜ2,?4 [so(c+׿NR>=2Hsپz^ݚteLqj^k{0ڰj) d汋5sEKk/$+tVltتϫ.&a:n6WL ᕭXuM ,g3YRʢĝ/i9QjuP>%, WJ?B/dUF'L|/nL\cvWR6pf?!yuDYkv=;y 9?sO*cou>eZJoiصQ7ΜTH[+5bC^Ż28$j3U[c{S_c[?y +^_VmHͼy#ewL춲yNsդ{~7dԟ'|7?zFιsMӠ`»w9wl~>WYy?6p!Sižj8$ά(-gdy{q~}w0zJ׿˨eg?%eӶ[cǬR, 6_d ԉ񔗼g<<*g킝q +\LyB)ُ*"mw=0ߠZYsM:;-BFMȆC>" +x[vtjJYI}N~UvN˃|Zur#mKmV1>!y] +#O-θv+j[Xdۖ1/♳WTX@Wl"{oʮ8T:zYb2޾(!{FՄBZKkL(X@^E^zs̖+&Wꅿb0u%_{G|!fKݕ>n}+MM/N-Y?]/MLl)/~cS~B>8ҍQbҹR5/9h=qu_Yo_rXGJSFpգR|2'UI>2_Xj_FdT]Z1(cx &$ɻ4IgEzZiJ1lt~fRsO ^&(~8VInV}~« j?wq41ESE̶o}m1}|5jCt?.|pE=/w ]bW/"+sAstVM*4Zd71w=[R2}'ٻ +en]$L>}5kE&6n*d,zTح۷JkY gCշϙn@+(OngE_y2\¾ٳCO\ʕ hV:mrGP^l(-U^v{Gd]g6wbi?W*̣ |V|Xg 78~qO~뾢[, #v%̟8皛=ޛ_6-;mEK]j*\{0ϯ7ϧD̼uZR~lGUJ ?=ˡBs⫻le>)Y_^TWf_"'UR|ҝ|\i?$:cDG W2~(Tݫ|^rp64Mzsr1=콣j"2퍚lUlN/g嶥͇ ;F-|q-:19ÇE^ s e:ܔ35Vgg0e6?}&a߷y_ +p^{ZՎkׇ-q\^%R$f(b8SQk/v$ϺJ{~\zk+_,܉8R"=,mW]q;r杪DW\kKl +_m_\dLﴇJ:}}a#aa_JcG.)+h_gAQZ;B]7'g;m_n#"F SLsO6S5Ik$yˍ+gxoX&7"ҽbBvwUW\\yEgic\ +b:h* yY#h^(>:=`Wr")q>[~2T99EO~nh\Cw"Xk[pl3DޖE?J:3L6x߄V(N *x'\)ҋ&,Q_cwu7{b_t'g:~̇xS>,Ql?(ݽ~?_^yCa|ĕl S-IIzY| 3TɗTT%;KH06̶1~53 o *Xmy+ñd0sn +\WYzKjtrVnw"Uz3Cqk + ͜M:aIeǦu;Ԛ{ +f\_be6+[؍8l˂LO98 +Qbhh Z߫_}1y۱"V7ƃR&9ާ 楳?%uCQLg*& ٢ϬRe5[m5}j]e BeZvO7}W.z%uz6צKSf]s䋶ߨg 2*enVppz]3>qr׽qjlZSaT +!Ĭo~J;` ??cf7~1]]e{KUa~;f~?~º+Q:6 l Qo/ӪV1gcܙ;$8_8&3Wޞ)szANgEm^!Pc97.ζfⴝ>%sMt\<˓9REf܏O[>)n /S~zgX7{5Z2jmZ`G&r{vcr\'9;~}H]m7Ζe{4[Nͯo{S?e}-A[ ޚk1m&gm[f~P gN4XޡQJlVv>&sM[f^*P}=?G_vt[Am]{:;.򵿟<ۚޮ{7yr:zS>҆)q}u/_ͻ{2$n~s:%/wHa65b#kV3*&޼[_ѳV'|.&Ii3k }8兔ĝe⏋Յ7,}HAC V6%f?,0/z9rև{?笊lajJ'Ħ3e}#b tܼLLy۪ bBIKNޔn!w݌bQ@㻍K2:O=4OZ?ʮhٹ5=N%⡯LMY `kcD㯖?[[zeA~'|1髩М}J %[$s/3b̜Is":%>.)6YƖ[nDPkB[FHz-^/a7l9njrij`ݽz}*M.rr6vg[nە_ u3n>~RvBUȻXN + {F.`,_ť.ȶ<(yzw;_<~!5Ȅ`mE]*o/(=c=mf+S/Xq{jܝ0OFx{_=p\'t^`迶s{YyTg:I԰;S?hӚe>L4 3Ŗ4+R ZC,7VNi#i^~ꈴmǛ;B7t 7Ylѯw6zZJ2/윴TS.6wn[Nv[O:Dq9vK&zWZuu +/^k -"}{jIW0zSXɾN?>7_U}hgN6rےnYWe~ eX Nvˢ|igɌ_$XC^/y嗳ccA"jn,S|wtF!-$hYd4.]vatWMyO{8w6e.LD=GdOy||LofQ'*7)۷{ z8r]w Rt{lU]0}\Ȣq=پԳ(|lՇrOitjks?2QkJM]go.9x7n r +,^.zu\ʜ >`ZZ՗9K5?ML +L쬴?p9*U֧-f)ߋ+owɪywŃ/Kܟ?cn쟘B69~-;XlN1k^}'`h7a/Ǫ~~=]lSi5[]Tw{(?}crW{_VJ!ޒw i-Pj˼WEdt+E185}S+Uԏϖ]'uDWؤmvK_7.ZWuV2Y Tr]xta)aqk]h%m\xyDWG,!xڱ=U y&NyR_"P)}b'zbyy"%Zgimʻw֟?S9'{k~csmbL ^ORάggVVٟWb +5tu((*Mpe1C43MO.W]yԟsO.Sbixg]730Wfř +~E=h /24C3*ON][w.5|{=oWR~u?=1'8 f_{٬/<#?־>>z/gIx٤SRB\{o;.&r6ݝ1Zo8%gY:ѮhkP!Uoj5?XYܳӳomʰçB?ʷLWz%7oKDu8pobU^JT헎ylƿs齵+\_'gq0/EE0uB~%|=iQo"hQtJ)Ǭ_H[s VG|&?/^R&["ٿ},~w՘c.'NޙThpey7uraJL70׿+N!_&|;3$㿁Mo/^RN^%UnG! +NΞզW?yyQN6-k# ^][{zq\ts֊Zx u]^mEF:|ej?wz>ah׾뇞a(A({+[niL3PVLz) 2g[5!6}3Y~4h%3\9~meVovCҒeg7%[CWP\v=JbYkD쒴.xk͏j_svB dF9rb֏߄̹Wq)ߌ.jt"-R^L\j51l gdSΫeu]g;{x-tV9Kۯ)(y<ꚼ֩>dpqT@Xz=Lg}:w{n>F |U{Q&Ʋ] ȟIӜ}CJsɬ"R˶-XdcЦ9wLjL{;QVݪռ% ?XkAP-}?p& 3G[Ι!nq<(YqSvO˳zsOO'dSo'vgOS:ht +φݱ>UGwyrމOLi:Ң8!r|3nͧ&/cuP} |e4faE\ђ?Nͯ{8]v#|b~[幜Mf[INQwC/&ZZ{f!矓7X|aSvy ֪G]\iVna%pmqBrZ/߻g^] l5Ow;%a"]/_w"-sD,[@JyÃ׽}>WUbsvqn=t=?_C%eɽWꌔ'^RtEقeC,XhEtr_k[f ݚے*Y;r16gj&eUt|^;-tK֭Rs|$7]ޟw?-#s"NS4LmzLU&_+/eӼH~X:o녵wIiGifgt̓%^iO.u#n#?Ub?p9mޞrOhvݻ,^⛬-?c._yPp˺gWɞmÐef{>.k&20DNi&mݺg?G{\|){q α|9"Sq}9g*fE `cf?颌[LKLKʞEw0cCƽꓔɴL-zW6S07A˺KOԧ;N}YfsZWt}/Ev^=Tv2^:crҳ\sA|Ҥyf6ݎg*ݝ|Os2ͧ?WF[4Unchт',IXs@ȂeF{vk9ڮ^״3˦ur&7EL_%,{hiA0$eke9^NJ~_%7VǗnܠgLַMkM:ܔ<_J:znUss =Y0dUc"$c9d۝T}rGV{*~nacպ1;.hTuSR̃fVoY>%ozbt)IՏv뫺$׸O-$V\rr>ҼEs:E^6q8gD\r:w؊u<Ζ30sjѭ3v$]TzhZScZ8&V5ꣻ/ +rZLywׯ:onlِI7dXϿsmR`ߺDe¹?V> ?96k)be/l>(ы<]mz#n2(d5~x%fm>|:genT\,Y8xظ'֮7JM1?voK|Z0^lࡰGb~ceSڌn)OO)B'ěݍJEyZ>igfy7"w6 z "]ui/=>}|~qw 9d5ldc^Wf9ozov/GoOqzmf~YoK||]~af7soݡuRyNjg*bbkwD_'I{JrpoWVjJ`}EٳY>ɟZ>֚%\(ñrwh2eAw<`lvzrͪٿݭd}v|NN:n0TYcזsFMqUzۗb+la/)e/W`t"zWk9a\ogmٽטּ՛iUxUkͥ< WkiNs*oJ>ۙ;-:BLhzW3.e5ξza?ԄDZS*}} +M8]5 +.IgUt!tz zYLPFo- MFV\1Ԟ,vn\a{3EVuZ-=Xí%,8¥ŝqT̞[FvsZZ+~*3YwadžSd7i{%YwzAKlJB.Y'N1۾TW_H[.-~#gWTV,M$iwsDg^s=;xaARy~/9,;]?/Ug]xG7{Xv<^}k%ww3wUs8ڗOs7Ϻd"sͪ +KY[Ej^PUmġW3>îҶ%&lKLQCK!B?x=Zz_ۏ>z;Wrwto)z^e36>oʏL'P͸gPlXͶj:K}XsOkupĹӶ(W\Tڽ]K%+3g#%9w_þժmqtG_{ %6|7t-Luwwɩe')?b NVv0ӦO;[,%Yڲ%7Me۔zco"ζFxT>qe + -?N. M Je}|PŞӎAͣ]͍=ʹrNpS!SьIsԝKmGSYbN^&~{O2vPb㓫7[z2]AY }og}mdwe9jY[/ ]\n}l}1-{퐣7ޞ{XWֽANZriPԔ6=v;X֌%W.uCd;Td7mK k]2Bzpwbpy|F;jM{U5`dWwRE@W!UkEt_Heq2]4-_:^cJe#@v_kUYN~BGٖ]_.^ͺ>iχsQ[v^gq/p8\k[̅Efi}TA8X)uWL?ry^o(M.mO\}& 7n^$uPn~ iUo[%5l{سosbޝYk?=߹KBrɺg猹O-DO@2&X9n-LPc49AG̅bSveVfԁ80gv1lZnL-KKw>$t? +o3IQ~LP9cR4|s|&.f:HitG_%zUZWV/4MNW%gO9MagfAӭUΘX?piOBj?R[tVU/Ȕz2/ >(ߏXuEO_50=͆Me8NEs8K$[^3E[8w&OM {D}T)R&ߕu)gy)\&ƖmwWv Ò~nseK)Tt?lRl۵a5r8#|%(=đtkKjX_)4^4=Ψ*MV)Z%b% ^c410Ŵg72/8Say }{Kl}}eQk}fh_LG6 +e_mY6ͤVȏN+OMgZD5S{s{X'$إ?| e'tYb;˱cϦC3,>v3ի^1;-].mR=^k珜j-N˼q/vStl-#e.m3=V!T 2'lY;uq^3&(fĭ΍>KRZiY|æ=2}O—6Ϗ_I_IAf`O=韕>~vG5>^9Ĭ9nzsn[ {ڪ_,K~tobLG7y*qopv2ON<ק\ٯBܷԛr5z\-|As~%ɳ|Y>p?w7}#[ h}襴 nZ!%;߃~?0I_ )Y^ieM}a__O~:u_OWq-yAԂYO?u_ɘ_oc_V=˜Oڟ^aU|YfI<ȑ +?Nd](۾{f~໿fCo(jgò {i=6lb:6T??⑆&c~]wUW}WpK{jOwVcG}?Yךi7cVޏ\sơ]ۭO /n/wN-wDbr[O?Y#[Dw#.o3u]~^zִHCŗ́G|rmwT%fxXTXpG#ڽ;Ý$otO3_S==2ُg[[{KZo]Z&,9/yݲ;J/l iL;-wn:kW]~ǟ_ڝ;|Mlj=V3k9\T}͏%5}WyG\׍v=pb/&j~yj%>o)SR޼zNSG)ዲv.oOn{Dv}sBN^FG޾u[msC>qh_x=m{g~r+:t'B'^UR\ܧZi'eNV΅.,lH_cˑl 7&K|'[*\2gBl8WOJ(쟫FbKV 9RƔ3hټigU*u2sR/4w_^,=dԯbuwSbJlXw4~[ﮫnNmgifB]J,<6GoHLW oܔQ=y_?w˓xh.]09(4=鯅֓ض?3eeg53̗nJ\Mȣ76mS!w? TZ5}7X|γ\s }뒎y;Xk*Oȵ}I|͝{6Ju)s?sr\)%5QJ8ϐRjjQqm Ϗ[~jFjk,ͦ'睟KO(WٺK__|ov7xJ\VvTiXS'bpet3G>dXMUCNktޯʖK/e|5f7W>fxm@ו|-;5..xtZym7Y^,tFq)ji8vK"2Xz:eN,>|-'Ū6am҂m_6>Ю«:mQO&n%) 69gRQt=K;|Zo Kc G3Mi_뇯?Rz,X~Fן>Z:/N1cޞ+s~x{Ip]߉}&Nл7S|%8N0eYd~M{aEtJ\W$27륇/۲Gzlgj#wkfX>y{g'088wѥL-'7+Ulwْ1{l9ΥY|DpL6MR<nhXΑToّQ*~ċL ӱ\V2yD5Ӥ3':}_)O(cM#"mseE"%m/c6 !b_5GٷU@BS3=<=NXudٶ5HM? {gkskV9Z׫VOIYN:OzwLc{wtPzb;Gͺ&?oJ +[˦m|/Pavn}W+_S۽Kk}#|_uq_WkSd>pL9z45-:fT>^ nj*i֕o;>|^?D๶3*ios _gwî?g-q=Eb +%g􋒥[OT,s˿>}kȨYܒ]9՚|We?_u-^M#urUNۡ>,W/]y'[Xd_-)XUM7Adq݂) 6\ +J}/|ٺZay΢E&I,huk_U8La3iePz{|v}bIGmjlggҟX7^T&3w_/kڹM_OΛk$ϡlا \&*W#}x׷M4:2~|r|S\ 3.ه7^zJVE+Mgs8syhH>S&s]JzO3 D(DSoo.˱VӿuwDFuvn !NL9DjHĊ^5uyyG2jRܣT'n?q)Vub%oK~9]wWX/ '$4r-y- +M2FolcKԟ" ~U 2D߽| 抢WSIm&*9^]azeuϕϑOCa';mg}˾흵z',mQgNUk솧'_+v /X+~y)%ˉ[L>DϘ즑ܪPf\ JO ٸ^"xݽ-9BTW)П|Fע,mT#g^?b_+bqDKcA}+)*K~2 is}--H?e{dԬTwz>H̬^^Oqo(e +i['yMԩ5{LT\8r9z\_suMI*j碀]14퐻ZSᏊbƢ֝(;m}jr>n7k{ݼKN. m}L*wQyeP=rcQ TrZg_ \riK?[MK4&I&ՌW&\\!|;;Ow]ͭ7# KSOg|MyF0yg^S]Jl1sJ $K/ߟb}ocƞwK7XyLjG|K6hazcg^ߵ_ L39"ǒgqb'4hGIYk)9k.}ՆLg6 }>lOߡ +b_0¡-Z-{~cq199?tKzBѬ>qFqX7sq_,eR_m_a_6mo>B/XK<LU,/I-X'mˋճ'=[.FʍSV|=$̹~K0H;ǷTH9ze,3&ٕæ1͖A's=,X6i_E+um&U5vWfIVgɨɶFh>O~yOS{*&^[.%|ϸn^SM~qUΪ6`ה>澳i cErNE;L=me 7My->M0)hb[e3@oWr{N?>5oKï<#i#bZX6۳y=_\fx 爛j>ﺚ5H\刳ԭ۴,{|˦3>? ʭ^% {b3vYԪo.{4]R;g+M s^nMkvLz&Hmeyխ*Uj\y}&á}=^7ٔoi1sɄ}^Kj/ƙ<+~qJ^ryt.{1Q3^2Kr.mh#_ P>?3~gl0ȯ&Gs"2OtM(Ԛf r +MbLZW[O;7My~蹾j֬S<%b-gHl2 ple oLrY^g2"k,U_X]*~'8/ 8jp>q7v{:k@NKDfRŔs-`pQ^ߌnד+.fKv kSkhyҡAWaw|\m}ߑ~?d?l`E{m=E3WH :}ZuӛAśIr޶ {WP%&/V]ťܣ[: M_C}M}џy ß|{v\eSշ7 7lsyԝNߥ<]ǘk6ͶiYؾ/6 뤧}W)9)읰[u83UOm=d)YxeZ{Oѧa _̜=jLk+C~`L0|KW]q/9T>Q;xM ]YXkg{~1Sb-:Ts|n+.3, 3t[7s +4GPyβtUQ|{͛Z~Qasj̎hxY>oS`S ;_-4yEΣV3u|F-՛ZX=TLiZЧ_W}mPcΛR)L+?P߫vTW})4 yY( p \Up:iR(G66fjqX{Q~I-.7t%l9=lpfgMvm A9wwL}m'e㗏gy4Ke3dRZVĵTڲ醆8.h~ھMiNyr[L)U_\/.4hx+zў[兖+rJvjW{ߨ=~qvO0K>AwګRޥ3NvLx +M.?q+M [mJ=j<z.~Uv lZE:{Ų/|= ~}v#˛L +ABM$ze7f0iּr(1Ns˳J@^؋]yatMWm|Ƌ^b(1YԊ_sg/R=yDԤgvKq E#^]$9!6IpҴ%Ŀ'eO5eNJ#/'orIe0lgn_KSa/i3XI${8g]B3ט{mwBʻȬ'kA9;k,u:ΙinV * `uFr˨;3Md5t888oˆ36o?{CuVn2/;hZ.gYtuoLK/ejƱSV}1vZW_ŔQpKMϬ(yێ09-S󮕟?y7M70]SiSN?g&h#^׍;xsHh[9g]fwvzĢR^trIm_(<grqi}|&|SOed 8co=pQYEp|M,ޝ~-WXHbR2fi=+n~nyt=ρKYy/n^gcInc]oƜK/藬\l[4mf^c^Z{ZiO\҄f/x_DTޮ"9h2sY__wW,˗xDi 'T,-c$wk\vt +IL\?}<1Whs8sR~0Uߵw4¡gSԢ;NGfdpJ-F" {*xѩFs"n }{_nSۥj~Iw9jYɩjfh^Oj͜b6wdL)Y8a;j~gls?B~+o|O_ΓR:6W|4+mkS%ܗ[iĊ?7Wn"}W7_2weY}导arM捷VZ=2MAQ"x7z(/~s<-k%kuÑ7-\ѴYӢ0=q,yeS#˧z +_;0c22Z o %="e=?ͯy,㯭nrRNT(8-r8y ʍW3e8r9keoLOu* k^lw5mbX]ۤP61NƂL) ~n/Xb';߮hG?Gpnگ,T㱏<|?wr_"z_;eCX\xkzRI{$Gsܿ1{~L+84Ɯ ?.5unRMK|_kqcHD̜fn]BުVV~;wL%uO\#▙8e'\sz_ ؝=1-o}.rz}N'ؼdi[Nn}E=1:vOuGr9S[eΒkSH\nvT(EbY_m(f|Lt|tѽeخ=]=}j{~2ykFZrգqײhssӓ,U|6k4*^k:PB{m-'|\r3 mf\fCLόo&17:N|q\,wU'{L{wkV&y76P3n yIz'_yf뵛k&o.*b` gN9盰Ao'Mp9X` #5m):sUo|ucҺ߾Bw;8T0bOFD&Ȱ>uͨ ۶ɜNdSUbi19.̔Էϙdͬ%t65<4j֬$y㮕]7%rmO#{swWݼUG<5,䘬&>{M/ W-XTk*r3=VlW}nx϶*f*]=*8o[ݵ#fi:-){fɦ{.>qHtoV)wOԚX`unZT{D)Zgܾ`x[k0?{6wn_͊,r_vqh/w6̳̾`ei{v,&V6a$}W WCakdOo37}Yu7K|WQ/,^T9K=dPZ?)i~5 |deeyN'>s{'}u8dzň M<0Sg/Tȼckwg _n}ZlΧ-KDuۻBo6R^⇾m"X_ޛθeD 1Nr)oM<\']e|xyB9a Xxr.wŞX=▧;췲 {uՄ*fH\ht<퓯=v&S~)k }'{ +/Zc+9f0MMm&Zio{nXZ.wϒc%V4.HJI)P.Nʒ>OJn;fٞ]KޘdJsw6FJ(6!"ͫ.oʢ)jo~Z7ɣmnWEI/SR6,^S;69uM`ZH8oVJa/9#.V.ܲ6 P~I_fbcjwsW,빋oQ|uwiΑ56=e51usQG9_j` f[]?:~[AWxETW#B5cYK5D܆&][|U ɮyJ ˥noXʺok^-15775G389K۶X5L,ÇO +xooyǷ6M|L*'I7-mag%fTL$tb&oӧ.z S)3Ɣ48^_cSE;Wv?ۚٿO9wM>fβUz>G:eRK_yBu0yOs{kX%8hOE=W|*,~c_ہs>e՛4ZzmwD<Bnmtfe5*\_]QSxϜ= lVyMSK툑L޿QYPó%y*֚/%4cۉ?W{sJ<4)K 6;.:pygC aY8鵏^ǃv߶Վ"wnj?E+:*R#fj]&1$OS2"&YWZ,]uuن/m= ^x^ &$IqPX)Ae[^{ޡwRT|J&4I"zS2npǾe3|:aJKc% .~pA[V[Gɴ?/Iq>᧡]y:.\|Z*Ŷ3;m{8':xMw[rY6|1T= #3M>8,6ޥ快>i4Xd#0J[ӌ󎯯IuI.ϊN6pYSZ-΅IaY'US^cr'U/^ފ'YN +/svw :qƆo_ugzusO\qyb+}V_q_MkgA/66^}KV*T.^仉i9Udͼk]>nMzaҊE-2Z˖[u= "zUrS>gMj76]Ǣ0iaw`KGx8K_zCprãO(`u{w~C rf=iifU"U:')%3,Uf~lyt/mKw)zonc +_pJβ'۫_w/6X= RFW˖/*WryOg72ڊg6n{]~u>ms.@/oOh;etM&y\3^3oCC0Gn=j>~qiޡ/+qֹh fRl[41>@i[\eR\NVl.OJwqy.u{Y1jvxkNk[<0 4uDLq~5QڥŌVkw'P}ίޞR[3_nǝȳ6Mu ӧ;~='/ޞ`7ou/o[{hη9F<'5rt^ЯGE2D;2w~H1.6=mWOùN}MG~Ož~?;*Y,R”gǴۣ%g՚%5bp^z-SN뜖{[!۠~U:Nal-+:~Ud:6we8_/5rOzq3Ozrl2[EY뒶<5&[g;}le+l-$U->>kb\0FЅ7gSݦc77g~bd<0ʼw0z-2|9nn ^L|Zu/Sscs}*1R쓄 8&m19ilYޓ% J)V-Ѵ^o +.&K|[{hv5`(8oWg *qyXl4Cٍk.eyxc} +}R.9ZG~ 7N3.Qη+[NfҜ׫¼׽}),u 76/k/eze~ܕ=_G@_%[qrHq/eKWY6iZsE3kdW6=IN7gvv))fWy/PN=n _nrm<}fM76){܌z/&7Dj;dln}dZmv`;EN+$Oŕr6}n ׵"W 9~|cgL^I~&޵=\#7[-"#'bm NL{z4!g1$(dVG;{ݓ5_'cҾ|5__MfX7!H~wqeO&L V=y׫-xoD_P\vpJ6~.쑅}j\]{%Penby)t=4_ʷf٦NLvnz#9x ŷ=1r,H̩}YHzߤzYiFn/S:o~&%Ln޾:=c_T3qS]yn-;NY8}-&pGnAB"ϯͿۙWx"^}kBN-?lmFgJq©({Kvf"n|o[YwIN-y L+s;/O͸>{[u٥q˫E- ]e0lrj]^͌mZBAV~+| x}{ܷۙ#~A93C7w~Zfy`qֺ]6K|t,24Nkw⁉Ijs ~yT4߃"$nH{j, +K3"!sAˤ)Bܺ{qTmƶ${[-sQ[_Ⱥ^/o̴3sI kn7 +}V-{y˿q6gJ~ W/߾MOBMK7>}԰D nBOg*f툖wz"bZRo0WaS&mB8Qw7i_\qJۧ7Mf}>1I;~c[{#,r.=v~R}'Lz},Tu :K2߲4:Gn3pޗgwmvIR= +$Ih +P^!EEFldZ _u;UgOY|ˏ/;Mz]rMܯ0_e[>zR+]YVƖL|/r&ר~;guy?|a[YW}էrYƿL +<1_;߿ФZ3~xtT]j +C㓯mmށ5_vʅWJ{M"}.d,߼_M|zk/֪OlCI=ElRxRݰ)E#Rw^y[MIGw}Fٽ>7:5<|WYuIΐVֻe:-s,kbR.4Q(-efA>Z[%L^+CO^[)'+IO%W}k{|upsʕݝV[KZ8)٠m9w o>O};q<%"3mu^u{mxqI蓢K~8b 2并Ix4hOf<$~ݣަܬ޴eWzb,0ifbpP˛ͼ'zПurl)7f=}M}-;m\gIzb_kyٓ^fɝ6g^(lR~uk[UjFwɄϽgyy6n*휃?^bavwEU񬢉l߇4J3$lPVtI\`@J[[W/;dtNY\K8-J^--;sfIbln +>;~v҉k؛ӿ$NJaKuѳI_~_~lY{ѿb^J[:nߧ:]皣Ug\ttF&+5}+BO<}{rMJO˄_h~ +忕RYx^U<4?cPV~ͽa-?uޏvҝ~|E_xB'ͧاJRRy \ Lw7w̙DJڌJWicp}c2 {JYzT _z9|d~uKW[GԮkG:.,=raUC]wKECkŧNfWQtbkiZ'xy>%Ҫ3G8\8v躪5䄢#~H쌻镨qNWvuʣ53zښ--?XV?sgWr:5Ծn |7]OIf+m&1OGeڕf<κkתʮUuVoƛ" un[4n3Vv䓍ܴm xݾ/):unDV{.̽W{vogˏ&{~}Y?;lUlj%uU .. 9K$e 2d1_0;.ܼXśqʶ0 +y8qZUԊ2c#6?5yȥAE}C%g}l|pjZK;ިisZkI߬ihc7W5x5ʜjtqh{Z G~pO_HdlNʤ^&W|tE^ܙ&§y.#6gߚ]X=&:2i<&W'7i lv a&\y}Yzn wTXW|ߎ=-_<5 {kr9Teu?⫖rmũʆ->݆C<ֶq}{e㴆o򵽑JOYѹpeE '6[#eݷ] + ظMe}K;}F˽p ].OC3b+:'JԜ\xueͥBg`~|w!kJXE")5k.9в)l>"¸rnE5up#"Yqw ɫ䜷"wb+CgޗBѓ?-*ݟ/rΞng.}d ,eLLYs+u3_QQ(I3ąV ;.ֳ_oK#yW*]:SvVmuuؠhŊ'0]rA›4^kuʫF-hq[Vۻf??lwi/}:kqIbcp릌؂gv,C>Mtzzq qb4Wma۵?{"w».nSog1W;6ѿ+Iܲo_ѥk{yU9Bd߻ >'WzZ({yne'fsblhRw!|#h%^-rhxOn4Y~Rw~U}2́iō.^ժeO|𣏙9w+L8IߝϾ:ɣ&w̏]_4OrK׋_ O6GD(K!~pUkTkRt |n+}[\[t/?o]2ƀE;N[Wpǵժ˦MzGۿ|rM7\.;99&Ī*_xb\+ k[J*/3>3e Ol2(91k wL^|qPnٚΫv)ĭs&`5D/ӧ.뎸zNn:YNr󨒰P60U yv,M[R͡&~2SYcZ'X"w3+w>xزt͏/Iu\$3b枺 +"fo%m7]$ykE8>\]8`#ű9S֊<͏xk\rns'}n˜MY&,s.=3;G&ͬ9/WW㚝QVvyMQ3K[)(7dɿT֭̏Դ,h.v?謙=Ʉyo0J,=FeČ?6 +}fy&싟x&ysOL]᧰iBҢ Kb08qѢD= [ +S{둱mm_X^!a~ʿc\+M]Aq뱬.sK8c'c—獵K?u`qԣkGUF]0?t~Ѻd +&˝W֬崙f1Br'\wRx՟թee??w'~8qgi-U_n=$>aJCg-mٮ5;֝oƑ/vW$qۧ $H%qv/Pj,}\ v:zK`U̼^+_qxb5;E'՗ 2>3qSRd޾ē'X6^3u0~/LR>{InF73`MmPK=539u37w'Tni~΢knO*nt~9;ylwi{5~%p}7C ^}q>#n1עyxe-~۱jnn:O +Vjn6?ܜ(y1lO,өhc5٠Pwy?O[ԫ?eú?&| rW~oǝsnmƴ^1- +#n?Y e$t f͛er8s9rm<6BvDO<ސ%qB>>*wf)6s7Z<{s}QQaW;cϱoz^܎^낞sWEXn j8ʹ遰kS81Z,*z[a4)?\ gĊVl_w+uʾVy\lڵa{럽< {`wU{7zWY m.I84)Ԥ-A'O^."<:ү}(7Dp`Y3s>r:a$YZٶy7rPu ? #*]$>|K'gq~S +8Ş_ISU:xBֽg6;kڂY{o?lg|yo;ZǒSmedn]ӳ_ђgϹyI%q#ۧ:w<ø?.IbW޴a5/mEɂK\?']FGca ;9ϴ(X}ݫ<ZF| +35,}v%KLy[U=4fmzrJ'}sӾlq_*-rg38L:YON|xlJKsMޢrIӕ +k\is$juh^Ƨ\C+Ӓ'eڮ.32/ܜ`YUQ:na)yU '^<9bl5HjGh_+W?.(]~Ƕ +%gdy<\e}}nSÄGip- S%SsxZP7O˅ߛ97cϒݗ;wV XGQ|F3uM4)WSD~ 7އ|pgfw9b+Um*~{&Rˢ懒b{ m]~ݕǯi,yNE}z[okIL;Wg3Μ(AcwjMǣo>= +z38r|lhﴳ2s.Rfg͙oT@pXem"KYMNEޛyW;adk>7.;͛M Cýߴ,_vb~][#iZ`.bi +l䒋;>52y]|W~!-:DQ>Foxbxt7+F w''Q+s7g}[_odn;Y=%w/N+͞\(T#nѾ938/`D<%禭u5hUX~ExK_V{,Exm{Wĥ~ᤎ4},dlp=Li ->{)uUMFTۥ雟ӢE,RD|e_eoK~1m=W3~8Oi]%ON.LegVLszfs/+o 5 IBKuzogsF̻{\2v-6>W2+^k?UNjNV%^872nkWLl0PrLO䫯$Oiw,KH{p:Qmnj^B"H +o@Ҕ z߻҉gib<Or8xMvQ+/=V$|T4M;U=IjZZlZ [!R+Fk_~newn<;tQXfUy"+V|$;ۥ/O>ߓܹKw)L=*E- ]eg߱H~ϧي}c22pf:'$n:-+jw9'*gsҫٓO0[PYђʧ}j{ ^lL7!x΂ s+rn[TE9ޭ2Aд%Dr(8wiK]f0I_9nYK܂_3X0q1:ӕoB)#V/uR`k& M-(ajg{VpQ w㣪ƣw2xᣅ{ކJ5HgS&<.J&ݓn_̊ɩ2J.OHZyU]RjV="H&=7ssN|T>̿{έ\uEZНw6)mkgןh|^,ˉ>kV^i_ty[]_Y0@XUs[E>z1YtO~TL}f?m~s7µI?7;e/wNˀEy/oJ)6}DG^q5'O5*d^ry}q(bc[vs*iO7=jsbքoVe&{{՟;ySz>%('cJ>VAqz<{Wt*;ʼNrf卷S.}_5K$V`TsET߯l33'ZGUGsflxZnΥKڷNWݺkB-g:8d_;t3/|)oSޤ"ys}y'go>ڲ\̟?*8,&8/Gͮ][=jS ?\yezegD.KtJ4{H.Ԥg|'dYSﭭxohd<߅Is%o^=)mZ:fkEiY%O-|Z-UIӧNҎ>}AߟҬ[=)m:<뗖d44w8;i^2qQBgr~ +鶿zȼSx/$kI?9%V< }AjIai +U\4w?:Q3v_LsJ15&`nxNT%~qiٛ{ԹxWsř^EsvOJ^#^F5b >Nw6?g髹,edpG9&~9ӫytJҭ.1럟|c=[Wbr (eS?kGiy,Y3Mm˞|7wMJ~18sLrtY0q F 'Ֆ~8hgul2T~4'U%=cv%++#~=1rgq}{ukT E28䅊L/rv*?C| 8d9-(?:fwLe9!UWzE;|9aW[6oUɻľ(`[E&O[s>=qrLW)ޟ]i1mžy)krK»rOuyoә.sȝuj9WLn}BSw{%>a _Xt_ޞyTr̔NklׄbQ(zqWԭ7g~8w!أ~O^IVqlߖ?ڵ.mZjT2j9KGX^2wRY$l020~YCEk|uvn٥fB&9dz§Dq;)i#";o0G&и0=a>TrSuB5y6=^gUE Jͣ=$u9XE-k +4Y~Xv;vZ o^W1ɃelRӴssJLg?SܵqLb7:skB:fw]gQ}xyDž:yzŜCo[gꐋS/?:H?[pi63㖥\9y?t[YqЯUCl7غ?mȢ<ފs7YvVKK,dzoޕ(X?%)S5WBjY7^ʇ͞:уZ{8mgpٕ_CV5LZu{O.}b$ݑ,qoQtyTsWOeϫR]~;5?镤lG~ͼu;\ls#|þI6?ۣoN+>^`JܧKĞV>jūܦ6w\R^WsmfftJx\LR3uGv/<]0uO}kgo+Yaz*D~ՁfE3%z-m͉WS,Sw37e[Jj 󸞋,dL{вˢXߴ}&מͺ3D'Y: +>i(^"_/Mi;a,X;q{ڷ5:{mY dZws +mZ˺]^rzؿoEDs.' zv%nNa{;ց~_n.F&yd7xf5;ӟ5wWD]B98WzJ)ڣ`{׹"?$J\=<)W)hGE6Zx7oov6_15kp|,'՘Qswv +=i)Wz,=}&>% d]dn깧WUKݖo}Bל};AS +B[5.[tl9$Gዺ 'I}]_۰Rnîr~_8Ժtފ M=)ޜL|po}v=7Zy&]x]2]vi;'^x-~"̓* uz A$٦,q6b{_pHUхgbIt9)o|3Otm`}DnVV|֓AټJNӚou?\ۊO73n}t%T.GrtVշs~Fy[ruʺԗ|0d{µ k%oi]~F)*&מ?L3RSz=X~#'V%UX=[;,#og- sw]ڞ'+o^퓌nBݩEfmK{f'"7?zPrMoDX_ u%yk ʵGrNt3:.k9x 7L4zum^oM/q1S,mU =`nwc2w|1}Qoe'Nx7 K˕ +v}$_]7]q Ji!,|VMbYkbXzM~B/}3e~=萭5yjNI₺mkuΑn\vl+-Kk'_)_eo;+ky⏊/Rum̓ny.Ug;qҝ}#ݫ',SrمM4z,Exhߎ +!6MuoϖZzK0كs%Jt>Ӳ;;&w)&Ooʛfo:qo%x&WO9[e_6]sϩ)JJ_y珼/\u]v<:mW5w%l_*װJwاg,8T4q6lIT?jƫ=z5~xܚW:}zW~\joش=,`U-hMsDOe-9͊ܭ70nZi\;9'ڤ}zaҭٓ'q++E&Tqyd1X?}/oxd{\06Xe? 0oy&3E|{Lne9Fa#3{A|Sc>~3xW>Wˇ L[˶s|oRb^aƺWSWsN?W?]e~@0 XxcSշeVK]R:տ=X_^lxP`Coۃf N۽['3쓈0O9Sf3 +Y!hBNqb9@{wIH7 +.vRƊy^|2C1'}P|ri6yէB+~]sξ`7We}VnuJ*snjz hӫMѼ8`t [T9D<;&Ļd6n =-m·:۳:;dr.ۧ|Ʌqgc +zuo$GӕӟT4gX-3=pokN]s* Reн{f<>_bn0$M}v\L'~49kc:WSݎL^/j6~ž՛ ear}D]lXOWڰ^8`Qƽu.(UՋkIwlCFѡL wͺ۶U?6{x5hV<ʆE&N\aceB*ݎ;tyj(gkv>Д[;/?70XO42sG @fޏnf;ެyytvEjorHz~񩓒_$OV:oZ}ӹwÛV泪V6:w糚Ζ{5[wI\znج3oYpݻsτYTuձ)hv3n~#S>-g~ +ќ4cO&wqL9y{=CGaK׾iyG[,lA:]9Z;&7ɧ%֯ jzơ~Igu~2u5Z.;ur[em7_^-xT|tµstĕCx'e&_ۦ9{s;&<|]-G^,cȋ]=t/ WeE{R?{gN=h/YO oZPz|כSvq/$!UwHqMdC .jWne~0(?j +XNkӰ]`ZxfMt|+33:ML]̽YΟ_K OQ9aykA[Үs"˷)bSy܀EvґvSʎgj WhשXazx{NWζ+;k.isS(ksCx[ Ft^qi/8ٿղ8ƚצuqEgqJT[P xqaV[fԲwso=#vc{+6M-x+fpS+[7dj$]~@{ˀ9) +<=kz̗8ɇ7JSϖMȽZwӫL%7I=wF9NIK\m6ޢZe़L%ݿ-P|B铽f3lܹeFJio6s0;(pҖs6Ng8fՖ'wt8ɱs-';1gB9_Z~{Jj-zi+6ukn%)"sj{q/+QGޛSNJܑ`ȭ{Ft%R Lȹc>~8ZMXs˵ >=&&;vŶbkPbeg\ &*Lp[.8w]Nu#7Un*U6sdү~_vޟsn#&S93p.\̹JlqOxI[̢;P$wԍKǖt[_/uF(yB{\B5 $>[i]/W3f7lxǽԳ5zU7Lœ +Rf}(G@[޴/H3[@|[Eݐ&|gvTtZclc1jի+ږrLE ?ș[%4l%1g1,hߙ6kQ k"4]S1$rV)N ВɓzF24W=᜾4 1Rs|X!$nAaks˜&i1ޏjnҽ˾Y/'W\ԧݻW +zkQZ#~? ?dKp7SRy^gE+O?c޼Baꬭn\|d_E霛gO|Y;t~ղESVZ0J|ƣ02t\:ao__Y71g}?'Ф*`#7/yf_O:)[|nOCiLa?+hc:;ݹ.FHHmpN[lѻBGKC8}S|r>7+oV <}-_T]??!>D13\E:Z¥NOom+m"bMiYmkVjd<(sxIu-Ꮬ:SڼgH~_>朖d'=Vnowe^pzDGnu͝(Qϛ$q삏g\8~n?Gox<]XR>tSֲncWBeӯ)wt8Mݢͮ2',ٚZʕO+ltecѶ| fatat\.zZ@շ f5ߵ&s[&}rheO}%/)tb>5[:c׹_t> ]'7|Rz[se[MBb'~T06/} \S85okqE.RO\_F/':\1H)76.L^h/~*9|Mtiԁ+d6g qAflO7i =tk.ߍnӹV|4}MtD9a.RM '鰼n5ǞmϬܲW OT/TzF0 odoڹ֮1yw9Q~Ԇ}⏛c^c);HG?G /J.3E>ZQO]lx¶O;ldVvfmZRN٫:Y?\`vz M"rwHȾվIlWZ&h׶L2܄.=yjrukT̼Kb1s;wJ__+sWK^z+ ay+|v nVs7I=z} zORo&-Oܬ9i7w/:kFIt{5;'/I^;yVaf;z~o3>pʛ닼gLn0A{pGk/,tڬq7GGj%my;^w:|[۟x }e*@^u\Oooy֑^[.tjs5N<AX9gdW|5@B.IrCwUϵν(R#^n@^ntZ@2k]lxh%kt f|!8Bۚ$YEJ|c\DѯU쾻, 4N~ϜV|ǸLCk= Kos/]}}I2C<%J5xN.j1ʮUߙY^]KXZY .JԻ~yowonMgH}ֵO4ct/SoV[z>-kq<<8lZ⇽IVC[J3^r糐2Cuiv}Ƌw-syE SLm}v6?3=5MMVd9v$ c˻R4ݸvc}vFLeuߵ_\{Z#rcϚՍdxݯnwi7M*_nb`{Ir?Ʈ[gмsCMm} ^k~ի +a{VmΙ\Smk{}ys/Y'q.Ѧto/ze~uYUCzGG[nY.Dӊ+WU=ፒq#'A IfS ԝ,:ךgM V<ÝrdElDj{ï9(tAgfCfNQ/zO秨&:}[`S k,믾`E]c-d軕CC}K_w%%߮MeLt=Esfp~Nʓ5PxʻGGƵ_`-UZ6儭f˺伟mV)C s.}iegl~QҦiM{]![&5b&ÓM3x<Οï{ٕ8Ck?ptFVFT'!u\ehz-vS& %5(z{iSo۝ӻc"7DxZj4mǹTk^yoE*s9~{ +ivʲͭnj8/u0ZD/BM|ke;e}:}koaOP(@ſc};9ߟvBgre" -o컪bA r5{7[SVyFC4OK} _YqO|%,|{9ֿ +;qif Vrϳy}CxOwn,H74OQo ˮ#fƌ^ϫT`y +VBA]}{WT)7ȫ)sU9O÷bojReW'*uh.{Kf+&=Yf#0!k ~)ef퓷>Hu_\/H}޺9<˝/j}0_ɭNLgħ&]K"~koZ9^SCپd^Şz..13&,[̷Iw,Y_lu ;f'yM}0sh;?^|^oԎZNV,,O߼7ko܎fK$V,pѳXx3??Y3M +--J2X[JۛCߤo`ҿ[]^zںͻO}i űs9߿ݸ.K?W|v4/>XpZn>%3m.P犰bIge8zO BS*d[ŘZ0H,wʃqpRfmu6Ӿz]p$籛2UN3)%ԯVȧ %r,V``Q܎;Uo;)kֿJ/U;'>ayni//e`8qD |Iim+eਙj )-te-tRc*[={>&9Ŕ g~{v')^md˾_vIg , _r沲s:mOPcaYK=7ܸ~KV;<+γ3Xت_쇠̩ 7Y]L[/|搉gddpF;|M&<56y]RgvC;]GYo=OoušW;}::ׁڜO;&mu27hۿdklJ(=waXK~Q&&~'q䓗Is^tGzho.w=mJfV#j'r6~41f5K[ +:e\}\]݌s⸪w[ףuXo޸jַ3ODB  Z^x%]#[?ܚ~UyEg޵+Ռ9N[zμL\&6KSZOq4G|YOW$jXwЃ|]}4[ +:[W>-L:brH6> a=Qs+*^uR{nXO^ڴ޻zMo77yVYl羯V}O|]*3O?HK5MY6L=X9yۃw?g  f?:jbi˘vpNP*ׄݳ??ҵ rZ8ފ>PwY_?i>_aRbtxo3>(Jl]t0L +fO`cWfz- UmOy"7M 3!Z[Q>^I'9g$0)= iadhg}6s#xx/xΟj3M.Ǖ+̤2ug˒V.4k-|w{]{^y6^dIۇ4n9Θ*'?ca/{=59npȍ;YoM;Lˬ+g]0*[VhxYz4<:3II܃j]j@]dRJ/1:qގ֕ov(-}2rwtZnHI^ys-SSJ#u.p_tE?ziM4\/kfXN&G +5 +^>ġ`h>u9¬O՗\σ`S>03:?0tqnx)6kLni_Ņ"$|R/hݒM0ZGʮ]'.vF<]۷1h_73\+rʙVr7l߾?k5V#[TVi:ǵOj[=g w5rd=2)o~p3'v$eG=ߚ/^e7Cu'^2=wf1]K&LoJR]^xT+u|}}c=rfS3eӚ拉L|StkXdΓ^'=ѻƦRﴗN9 u_|XzRoafoVSݞl-:\6g GY#IcQܪїf?WOk: EܸFuyS Wh˲zNo}5wṈuZ.׵b;?[ni6ײɉ+06d&料6П3"#C'fx8U%D +hXpƳY%_OO{nn([[\sʘ#~=eæ/&nk<+خ8Dx> ;zߜwVSxR۟Z-ioraSD/2tn' 6=3/Fcۿ䎹6FoX;OƝG4~lc]T/ueo t_آ o/Ii\y鎒kSӇ>実7ˤn;ڳyk~s.ϥQ=~~Hыsμ &g7?ߢgvra:7nU>r<%(t`?}Y B{{߳Q]ZѿFYdv,k;ppy8:FD~Ty>}\6nů{7^+c-a3678ߴ'y7'{5sαS`oOLǼMa?WS 3R{yx+4hpVǽ%JA9 /kQ>UQ'n/|ԠoϯqɃ|sڽO=rz۾{ZbN476&em 6;~*'˚|Emg8ewv_O/17(wM;')sPTK-}JjءWs2{rWZ6LzR>7w.,v'/^;m-#jr9+޽֢q,QT/:tc/W7[ؿOq$Ňln߬NȤ\xMEDN|]wo($1.CFc=W6e sA + A_+soNL̶]}ܿi\Q6gUZLU"|0@{ޛ{O.R4$ȼY7nzMToω];yݟ4[ݔaWorw´DۤU4|wC@0 {NK du2߳|{|1 Nމ:gYBux]#xDos+Tg^7zZ{yvK߫voTY31oO+]Cy?Ⱦ`%~LlΡ fM+e-,١w4Ӕ}7NXLVk:Yexvoffk}u]ȩ`/OEf_Y]:zѪVᵑU'J8dw`AeΕED -ѳI2zt&3WxvBM+%M>ǭ?Ti/_N7F-eo aop_)$1N3ӳwo%:GUҍ?X*秞z*_gr+={]b=ARU]6w8VvUb?\,fBoktnl2ٰj,6G_}m^L +̐<^ cĪI_'an,ٳ5=δ3[s8#6a1os~٦V".W}EjwU?9&UO̘/9Z Mvrͥ4wh١7A"Rt[s4]? Nv5pW_[%yhn~d/L+ߨgwb7/_٧ϤlԢIg&}L%*3f]u׍{k͑.|KT!`}^EUO/Z69Yt L7:q}읶.\S+Rp6>hNjoz}ay?b79w͒ Z?}uyAWftL.\#X&]VvILzNV:Fk2LwN2oUb'@_.ķ/hn>icV)?E[p;&A+몬pf9/޾1ZrCa#]Z9>l{+gK=>YwL55,~\wmxK+z_;&n(q7Sr4v1w ~&"^ra 9ϰS_fV#?;2}7O4w݊7\Z37U.=S9Uzlb"|b|%%1LԶ/Ogc \EosJr+t73򇷽<}Aڳ'R7<4}Ϥ +ZYo]f-m +j;xfLcp]j+]w=Uty'N mK>O^QxQґ3](<+k!FM [ﳍ-g*WU6f]O )3t Y@"|5Nޓp]3O$ևm=zGׅoZ~IG?}߽׻ty_րJmT8߯OY%>'<<4w }3_yK{+vmکLǁ+/BneY;'yQ_z\Fњմ2ʪKޚԧ{[EE\նwZ?;sU;j崹lom;v럶LJ~qދtݲ:5㼥|ҷ|{qK>k~2k/*tl҃9#}#O>mkdiW\C#\SJ*'jwoޖc'Lae~^ݧYm{;")\[w7N/t˼AU~COyƇnu +ug{y^z;Rt:ܮ3ȟ>a|U>M&%ܟ}sՕsYXtUǭv?.2ڕcrWK$"t]$les(Vs 'S76fO/ TĝYSu(3_3uRcRJpIv GիNϗ]«kR ,/"V#0}ϬV.t|kùL ]⟗f1M&RL]M<3o^Q7]di99|? ;sgD-.lPq_R_-;g.c'pܕgW/FO/z'2w<,lwj]s\tߊ}k?xD'Y)-q&S뵊tڊ:b\۟*|BWB؊'v.dUPP>~mR*Ce2xjꭟYۖ,q]Z{o['{okjt[;Ń=+yiY줋K)X#-5A7|&ʭ~%Zmd{s7yzqhUUvJ7]п9fd\۠>unio&=RTl_+ヹKe|*~x~=+/&w;Sʹ>~I8l_UeyUsSeuZ KE,.3֋=B\OyRo֞p$#%_H;dLek#(٣]tQJQ韾a/DZ _kM~y ޯw>rD)X#J4ngCnWێYg9ۘ=Vof=ߞ'k4jTu [}x4/WҖӶ7H/;꣠ dǒ=֜t_>1i*_N^f|t7^nqnDbgwٴuŻmb +y_}ü %U[kcgTy~M;} {Fn]뱇غe!?>J)eJY ><(/P ҿ_}RCk6Q1Rqۺ1Tt5Ϸ'H_.]b_wgOnqJJZ8թ+N_x/Ssz=?H8P~>Cc=}u>|ustNy[$4~ձߚ+fMa`2GFۮʹ7OIK;ٖ.ۼgNKDNޙcBvg:˷[a6اh+ +$fd6/.*ӂvŹf|UQh+4eE} Nw-rNi,~z~8{NyI_Okz۾w;XGM_\у_j\7oڢI7#SE%\aՙu`9מ0޾@%ϙGgXp׿_:gaCCY]e>%75/|ij7Q?ƁF-!_ԗft~s*i?.:+TW-RZikt5?ZvekV9 s~KAGŮWV_7B=N|%;Ԣ̢Ȼ.Ɔ.;#v7{rX~󳠣MV3V:rO;lbk _pzR/j_v~o\tgU?ՅBV5~-y+ρ _j'j?}p_蓧ɺH^Riݥk ذn\d:yj/nΟ~{1o * }}՘JO⽽55fu^oƞ ?gZA̒ +q{ZZj6:)<|#U_a,cY:?wɞә-PTd2:4ѼG\>~4qSS?W:/z=5 ++TFI=(^*Aw/iңW-u&̟kU.g<};BR}wTIR7pCe2nw)gY[c~FtBv}zI|.˪flnke{WEU3ӪsٔkNMQ]9Ǝ">/[}#.x:kwϙSCM6Vj1/=O;OK/T?N]jysftxjia'8eMʚHx/׿}o^X/=x&ɗ墺?e;Muӯ]K@ ٭)O<ɟ>Cr̎[e)'y#_rtW +VSYR,yzvrW^iڧncl=?_d=<ݽ,_Q:=t}"O9{ɺmI+G}RwzO\qݥצs5;K/ +fXxe.e}coe?1w崽o9 +uIJr;lB&SiԻ9·l]4iھ@GL~"'n>]HIu_=x ,}~-nԣܒV^xI~ZMꏚzn1 >} 7ws]&G b+ώ?e6kխS-MvnwX0]ˆIiXOL0SǓи6g.p6]SrCUn.wt,97wzōO9=[Zr#bٓ9n&.̍mf~YqVNFa[vʥۅ,?*u}NKXX]dƖ ; +$_eVqʇ u<ߜؾnjy.ul$Y+]]۱WIYL 5w* Zlp|pak K0Z<$~̴%鵳tg :VYS qT>5“rl97]zWzݕ} {)wT'mdYd/'l9+z>\0C MV:^oȞ"To:#JjQ}6PNcU/@B|lLww]d[0Q}疬ܭ-`K#?9۷Z;^|IyFF|I"y L>?tEu9M^LӚ>3:nv7љx0,/Ź$|֕so}hΙoldw|lF~vUm>> W=(5_c³-xq#ƻ,3̸trl73dk'9;:Ih7cV>!>;[h%n;Ȗ0\UN_mz*zfԼy*/\8գgC/oEE/71yū׫k>gMxYC{.ߴԱO slWhY^U=Z'<2y]D]Oreu?'6|e~Y8UJ8q*l<ۭo}mdk_OmC m 3+bVyJ)9ogn{m5\/gowu)e7J.yW9kY\g Km+ ?}`rPƝ>_:|X\?]""J>Tv[YugTH|qܞ8KH;]6{?J?-~r}riRBu3WmBM6I'YnYp~'g\(RԷSմ ]8|ǃy}soz@)?*N,\]{ͼW;#蓮>wq1܎BKt=e%î~N+C_Hr3="X[puѳoxgzM-F_=|sMج[v- +Ym'%M5vk[g0s2J/^9]\Yժ흮\Ţ.YMݶəf.æ`)"1o[s;z+hzC󳯔cöv.gQdnӗƉs1]gu||ORaNgV݂{Y,VxE]tgC5?llٛR:ְ?Ş&{-+O>c45[N]P;>UrVYH3jvV4Qmtd,x>sM nVr ́'n~DoY>ak"O,OuߚxY +gkwuqlG 5rfM Psѷ d\&z1]OJC.?k\{!`r+>Kߋ"{j]&= )oj]U"> gٿSfsnJcwXͼc+IavÄ u&\LΒb_D=|I^w7̍-6^z YیSeݵ̔sQ?o@c7s^w=n[Y^Dt(#52}^\Sze=nqKꡖ[//^o'X0tz_ٛDE+Nu |!83G=soq9K[c=n.W7Ysϩڧ!pPw92 +{_<2vl6>2掘Aۙ7Z# +Vt>ֱIo$}=ӓ$pIԻ>9W9Hpt 'G6?5|^' ֶ.b7>f_85W sR9uQgv 7>,w5rU*`SA1݇#zY,1/z]G-wL +Nʺ[q˷l{?sϻ9{fK7~wL~+ELhMes}yW)uzGCt;1uYk7.7W-S ~3ׂEv7?.,}N +\u +)gQ5U,=S6|F݂ ],eC%IG-'kqpsC.Ve#qh=)ίzƳ`?[+/[KB6?ϖG?Yxq^h8o =yY짲7L'N9`o-_7:9ô^;l eVrx٥c٤歵]][JG$W"j5);I>]٢2ɝӫBr$L4W|{Զ3:|L=1gAGUYOk^OaҮDk!Cg<3Sn?>q3s(etuE!#W=+6I|5B#s7 Nwnwfdq.3/Xǽ/8' V72Hnޕ/ 3k/7*_a`}f<0s|(:b}T{[&տlpwhB =jrXe3(_+F_V[\7xY&/BpC?Gq60LZfkeońg[=tF9:2S ''8ǜjf^ǾR?gqelk}U=" ;<) ++,uZ,L+\d!сf٣J3M=+bرޙ27'pr3cqbЌ3'wL:NߧMz]ޱ5&Wh^5]'rݝs51rVmu~Eȥۥ6/me)E?/eסyzqy2:>G|,vW:eFSeI>8s̛/9my_J~.^R3;(Ժ*{3{q˭kڗnyӺ߿UXo7_'(ix3j^$`+-L==$YR}w*96oc*gM.åZk9o hBU*]f:d>}h㚊k_:2YR@-uq| mu?j1wvʭK|>\nE{٣W]{ߘղ`uݥЅ;2d +X&_(TѸwRVH|*g;'j[;{Ņ{VX9꼝1YeJ.fnx Ւ|˺|o5?\Üm;H/+쀰דk/ϵMWuo^],vԿz*n$jBշ(иPɂ>M&EgV_{[ޣ_2箝ٿdw7\:sՆ+F9_:*N}hv<͜"o/TI|O$ sGzۍn:ڡiUΦ\'/Z$ s]so@v61 7w" ۣHwW7dn+p&ߣD,+ ) 1tXͻzf% og]"G+ʃ§ g/j:sSS.$G?8澔i_[yYߦIyX2װR+X>m Wэ%S\XZ1p'/?, Wӗ붼Ѥ]7/Ϻ^e{~4Zѳ`B/ϿvAsyKd3cpM]/B/y ˸/(|{}>U?M$mzU);=|e/^OEb't{y,7oe^JAC˻>?H߫Y~L<8\#_nu0E8_N϶XdzvFKs?*Tfl|w=($+9{~u#}HNENqSJ&8p9٢Snkd_9ԅGYo_D[78X>M9֘wwCSBko{yꚵr:z$np:(i$p{Ggj+cբ+cMM։ksc;Fc;ܴCƆ֞ ~e07w"jO';W1`^=֓~?Cq-g WveMˏ /ޟ0o +O|Rtc ('3gr_uN0oLo aK?<gv@H^/Ry֦ȧ)bSؓ]a6,,V3q9:8T4*n}η@~#j1+˺ pnn۷+gp9C+gQ.e1츽$Utf[g޷|eAs_EV[&JwIR;uVZ+.~_t@&AmoӼ({7܉{zGUе=BbL}k )оhM_.gpܤĢG2:[h}{}>e*!Ol~fRtjES/Sr3]H͸C-5B,slTmo;-Eߚu>N}wkSˡה?z1 $,^ +.ޫF7LtDLJ޽VWbSji1uMYL-&_{0ڣ9x[C.}_1֗my={ۺƶqeMtx +=·m/V(ժm[ͿM8sjnշ{ \#8?msmC6Kvuś-W$ v\wf)k⊋U4L=|Mpvmm,$YE[YwnJ?_z03Qn",v +OO킽ڜV~Nw'f4z{+K?)Ԋ Řmq ]LϙzcZg^n7&{\Cw޹\_3q_}>MA'5OxU1 6Y͊OߓgtV>oc}yHoBVz/?-z~74lp\!=q/sܤNxyť;gJ93dr ?n)q팊i+K(\?=kaAvoI mr޸o%²"!_x/\7mkeTN9aNcX{iIZ{x[z2E +1X[V=c,WKyo3W}z^xs Eaq*k^?yMSVӬKxp[ _q.w%Wy6Eʞ +^ ޖbE{+Ngxl>vKȗSYD썟k!Q=:_aM7{.-ձmXfXBl|grh5C%VpKY=;iˍs2\X]@Os-9 rդ{W}8zyUr~@O@2ML̼Xl[冠cW-|aJRJL3^NM}Ie[)xtij;6 澼y7wЉ +үb_:MmgqiʙVk +~qv&Z ?vSe6+wsAiZ>K3R\wJ_ϑޛM?&5_szd麄VW:U#9 z7,hJ1-xfJQ}G.{V E?un[^߭a~ʞ9 t5V`b鄇x \M36{LJhEJyeӧl=^yO}[9'*Y!ϴUszy9͚6*lZеq`ߙye^Ä1V-]v6{6rvfT5u+ +ި}3w֭nl'rop {jS U)VTitMM9W?_ymٝ{ޝf^enֈ_]uŎg-Xt>|SԓTL$WS艛R,vob3}\_Ԝnݿni;_-ǵRJށ:Ev$j\hy|B6e/Nd{9.SvۣLX{Ins 5uݙ{(%lFe#JIIj>xmɺyXL{"gnqOq0ڽٷy5Yd^ߵ9*elд|;yF;j̹l:[fJ4OT{=|פ#[lv +Z(&AnOĮ62ϾHD4܊[o~Ϯ=:[#"[L.ߥjey{z KUdԸ1 _Z36eArܬt%oWS Z?ELXy]Rޓ.2޼>pH+gg{"xuwh1V<}ՁWZY.1CUo'ٷ|ɯ?_qwp}pqBlzlv\+:7Z:@{| /yX@z^'+~hW0y͆3_Nol[)U4;Ewj]ݣyjo4ܜ_gMv>zvMԛs[bO8Wwjj +9/{lf%<;z!"c7Th\TwTYoV{2僊>4ߺ@&G ׎__1܎̚NJYv*d1`čie00j=7mE +S;9!-l%eVrg73}Pؙ)aRrCnxh +?+ +{=]_5Xb}iJ/Gmvfyqv=&HT:SSUR- 'kՖ~Eg'?TӻMw)Yu^٦mN6l[fy@Me鎻oں{ek[ľYc̖XzV:X?#%&eV-=2WBѣ<K|R9_Y既E- +Bg +]pqxQLƥE k ǪGp9s]jA"5+ZBEfV4Z_a!|<ζsu1|=bx[7Xս>#SO7{%e~\;UyJOY`qJ*2WuWȪ# +m~ןسuҔn\u'RT],R&lXbBfEU3LZnyM*uV+3>z;]0^h/wծI+ +NZ+֊;ߧY0Ş;ku zY-ls ;*|+MJg[ g_Q^2+MW:OE!a5@ݾIa˦|Տ jl_&=MGfM񏏙nLYsRf"N1Ư}|+45|X/ xmNϛtQ /ֺttoy<_ëZw,I{sBz.[4dKr6j_|-ԶgsjH_yuwg g8?-xc1kdͪ{zξӖ d31]]+Rw«^UoRIm3gR=R*> +q.Z4gՕ}簫 ';aĬ?B7[ +]13, Cʹ"MVU]Yq5v0Y;|mZm}k}ع9 E{z=k/}L[`"`Zv{u6Y}VXF ƌ_^,g,;=X> ni]+ɮqoj|"ssڸY;` ar[s_$>yc.g?$_A:U79lU>wCDoMYKۖQPS›&%!ԯjs]2z%z~9';+gsb{ +~{DZ>ڡµQ9Wf%ocb{ ,~◣ۅ*q.5c*QhYUS+-PbSWg|XZheo)584qk۾ҹͮ,1]JxVw{-T0/0 ;*ro?4A]>=h `bUW_0no忊(9OՎQ3m&>ueSd? eM,RdySn/w3Ÿ[dBtCɋ +d,9r½&_'9]MXs0[_,v^4_ӹs#dڄ.pj8zSα1a|tw}sDmxń3)vO/w޷!NA_ +{BSf~|fY_ W]y뼐ƛ6rJISY^?uzaWdeIo?>|U,7O,KY"- m-im[%ٌp7+TeUhַ$aGiOL< iɺ{4 Șv5%N(]k}9à7l&O(~F + L,Z,ϝKHLz }f(߶Iź/5p4O2Y+;n[O{R-•> ].z!b.8e`- + 픯޿oCT֬~Ѽ]gt}$\eF^9k%%RmS7}.J=lÌ)U]W:i|xoT|+/PWς K<7ȖYtPd;ϊwUE3EQ=(cS<*OUdJ ~b vIs~gL'6x&G,Mw8ͭ޲o߾Zk~Go־tщ+_Rkqkny{!)uZj+:wwӴ}{YBrK;nSH…o}ԝy}o;dϒëwP0!-.~pKwKO ,쓗Z/B%*:hwWfǍMp"pë÷ت1+&+,gN[r [Cv}ZByW)ӐM38auܝq?Mץ#J^'8c~[,;<[׋co/쳟tNX좆V\jAm=Nq'|yoϝQpb߆I}fђge9 {- +}[ O:l*K_hjctB)P;OsuMo7MO|a_σ_g?`^&j8n[ ?\ hհKAiebޭ|rnw +>;lE2tء1uq%YsMJO{֗0+i(5{ЬFsf?}{uWV9g͍kY'w^ʨy~CuB+/qG?& Wj3uxFG3TX-.K?:h"+otײ/lo'Q[ ,_[3wCi )5}mK/6_^svy~̐GSdBs9wVi~M7%cMuo*wɶQqɞXp.ŻKcn(zGZoy^͏MsٿHrM=iʭsj^ڦ7tE]S͌M}cm3~($Ml?o8ojcv۶y=ۮ{v~_>[=RfŕN]`BMc<oN=ʇ3rݔN}raybK{ӿ%;J?˓=*-|lVZvLN9k8"sJ^ܰ\&'Sn˯V԰F˽8v\v/,)[4i}4K492xUBԾcz_ݝ~S{yr`Տ^ Ҕ|^ϭUStΚL|g"v͕լׄ}V~X6u};ݻGW:{g]vosmةk?G2+&[vҵ[O*z˓xHVRC)?^^eG̍}U8n=9+7d_qwVg.ז&-Rt̹kϾl^s7V dzqqKϏfM;`~zNzdr!%.lT]DH&)=!DŽOfg-'qNwPf{j0w4zVu{fmx:ĩo%-3%)j8Y|f[~ߕq/ώe1kcdw#g^9﵋U 7Lzt.S+>_,Wܯ 26qnu>g."2՝?1ܔy$X!5d폵:Y0ɥC<'cOT1=*sXkGj +h s>p.mZVr?jkD1s7ڣx-r\,dԄ.aٍ;R&U-!|kfӉ>=ҍ7z}f}j=d#՚tHe{}c(Y{VԿC:]- ^?WTW3ZͷھIa9-:ʉ:1هyiO`},JSכg|Pw;_.c'.Ɗxm7柗YǴwҞvm-[TKp NtzME'XKntx+ο*>F.3SҶ'0/+ȖVJGϽtCyK{ۋZu /y|X[j5%^qgjb鎫׫OkW>6}56-Tz_[E}Thex/V3=uox~oÓ߃{=q9Ey2'}~kJԙ9z)ӻν+幙`M]qMmWo^tD] ^\,?u|I}CENOT\rwRţfꦝﭙ%[FSտhn@G!ӎ{Kj˙ L;,/]~^li~~YZW%.vZ!y}lRsW`*ݻ9C6@ [J]|OEeKXܶ|M|]}NMEfZ L>_wֻsucmFB>w[{XQiAE-%un^ĮCf{-;/J;1]R#rF9](Q0)mZS$ޭS=alwbYq]jKO]j[<ԇXc:y&m2ͱ| V~>y&VcW`ꀵ/WS>/,[\)cf:qh7 +mxKoϹ*;Yvb~YlԅZv*>3]w)l]ugm^eCo&,}̭o7RILv V['g:ߕ_9ּy^he{{>2p_bK,ױmϛ?|fW캩{唾^hOqy/c9qa ԭ{ޮdvTz6M2˖{*gt +m/yp=˹oޭ]Ξ׏~[ʽЭe?y\cJ7عzhl8 gW֜=>o}92潤rF+ߖ{]ߴ=׵u19e8=[6S'xLuyarEo6]-Z|%s]^Ud,V璥En6'3gylw_WF*l~ j`rxUB}kߔbq5OBe$﬽V;ݧm~_Ͻ>$zK"wO[Fv7^ۧ)z;e%LM_R}={yI47"~se-|_sy?r%cjjq־X_UZ`ӑw_pF p.:s)gɇϔ n>t"pd1M[:>I+>Iqirs_|ժ?JA#=Ķ[?o.ڹP|1ׄU'9Zkfw͗+T/u.z,WsWzdx^Ax\'îswyhD|hXk}Z0{TLC zhZfXt%D5b)疬>\Xx#'>i1ΫՎj%T2^xeE镯_Nsڗ/6cη˪uqzFrRM_&\*%Ml^6Rg ?zZ釓Բ?_闒c/Rj{UhdyҹRȫ?~i˭vg;gPl^"yk}§ħK\:(}KkY>g4z&%,,(qo +1w٤n-J9Bgо̮zK{}d8-y8gyՆOOR ʵ3<_~G[Odqyjòo}?q6?oKcIw +n.`O7.2I(˹5gì;+Tf .xv +kr3$[M/guCIn|睻fYAtN]Ų;]&թ:*B[ 8[T .<]NݞIJsB՞Wx]28"=:f+b.^gۯrvE圔b__GV/2z`,.jvZ ;{ٹ ?OxijE|C5b W]Qe?|_^ۿe+J-|CzJ{BL~^%?K;,]_}䫓-x 8ynKoMXdHoO/>&L3r-ey&I%{vMГ~vZ͑SVv$Tz#am3[ŴeO=>*v>s)绉1sw+\*&U[}gIiN4q95wMdSV>j2 WI;Nܦp+=( O7}s8U˃kj^:*wͿe֊MbjH(9[==_龑ҿPkó3g^{¬*k\A!'ѝQ_9< +h= :_`Ihʛ%fyሑֹLjg ϻ\cql ;w?:bV~hv߬T٤3S_|}*ݕku7}yߑw_f&M ^ UͦSE[}EE.Y/j.gl5$?׳apIy|,V)gFf''},d<*,"qwngz&vǘ'9M8oV'$Ʊ잾's[~#$wry!1h/tdɌ(B}w[uf|9 +%t&_,-357wr=P8틴νOm\wxo/VM.bS&3 ~qZO˵;uvrn~bYQS5eCݕ Rqҋ{ڲdle;{l{C*n8um-&2LuEѠgl,o[9hOJO_JT&s,^a<,?М%U_Vn#f>1!:ĮFOѩ[t⵺=n9 ?xXAUg_?/~ྲྀvK9f|(ZuWrMLҋ_+(K\)ߝ'm^͋$092g* Lx)NM>(}~o@2:fa%<޿@!Y#ΙVwwU݆{neEzݓfK|rȵUon}~.o|ţZZ2 6]kѿrV޺[SlN˼|s0]K׺gG-|n-[ry7Z׼߉?6LoxqB1bMS9!VElI%nJVI;p9CdX\1f.A?ZUWn2+yo~_HSe5^G'ݱ2i䈏Ee\]}#xoW{ɮb:rsiLUCA +Uʞ݉Z}Vkyg7|gpUm<Ç s0c+3u-ٮœy1^f~9Yo~mUV{a!o'yj{_ts lka%UpujҌ )NኍS^T*~89ar|Y=nԄ#v9 i8V^gck|cݱiqߡM{n:M7*ɒ-˞rp^uh2㗜l&Su;fɖO:'=_1kRS+'7/<`=_OmGyjﲯ&;t>?EѨӫyoIQ=MǷ_xFjm3]O|NfՇumjz]Ww*r ,OT +L_?-s 9ZLĝ^]il¥fZM{k|N櫎Ԭ Ďޛ}VIo;SjI"6_t)91֊S/3.46I6Q|lI9aQT}_%kǪY~P[lMG +!Mh/tFGjm6dLzXTxz?~+4sc[s'\whvw痸.WVkKT #{ .} d:9eMX9M;*`nYݾ'HuY_ȽD۱Y:I'W6q wc֋rJ/Xʽǖw5W~?8ʯͼ~K@ˉ N[m4+|ٌ 9&ۓn6 ͩmج5W>a`0Tl;؊G'lRD;|[ϝzlͰ~ ܭf400L.>ðwݲ~ =*iUEyӄ:Zےd)AKjMu9NG{wlW-3݅ GWf,vsṑZF=!_NظybtY Z i{>[=)`)Tbz.dM?lvki|t;f|3-fGykϺov +kUz:afk5_#Q'6D?cUfOwynSV|iqܥBTyCbD*}-(s13DxEnt+#*mJјꛔ/0d.Lw׾S WY$]9x]<=]c|'v+'~eڲBՒrbk&q%,WL*?z;!ղs;Lko-Q^|M__{)}K~3zem'E/?ż)#jݫ'P7׊\vLmK5/V=ԡR]Lz] UjWfx)ʣ>׷{~Is\r:ȸxɸO<ڷqǫ6 w xw,r*C/kƺh7V۫b|Vⲙ򵭦{OdroE-۶F2}O_w5^zM|o'͏4o/S`g{ǞN[5#Q'7hB[gk{/,>jƔjYPϭb$Tzפnݵh'9.Bu*rlȳaKC:Y\>N;?jIS9L*†q .Uo =O=iS}FuE E|s- +\]k8;CSsJ㵆yM;kOL~y}JijReGi^xd NsK)%+?vJ?OlR;j)n.䒚'\M_7Êʚf-x{J ͍fK=߽/&k 4[Čw -ͪk7M`8׷>r^K[3?. tBw&u?W^oՙQLQp'Ǔ [zgUIsivS;1uoUm96e&^Wsq|_B353,?l!_Q%_S_zo?v\DNē7κp59QM?UL9W>-}747}7:°F_ȸZJ?WgO>SО(p]da`x-FǏCo~Dmf:,O:VZ'3J:6-;_p峹y L{;3CrNt>aۧHm+\L{v_R{ʳ3^leIxwM>uI&y35Yqu˛KDlD6k.Տ>-ǹoڅ|y'\\{g]Kw&Iݳ>.*xO,^O?5Vp3wop~ 7זKveE M7kK_|M4ˑS㻽2ݣޯ.vSͲf[KVY[Vݎ^d0G3.~}ʎJlJP}QRqhNv7_f&{K{yfΣ,&ma&Viu{Lxih5^/>WZu 3kbWek]qhzkk(S3?qq=zA?VD`/Lq>3:랦Y#+Jk6[eo+yzIJLy%C]'Ugֿp-eQjM2x^SݓGM/,{d}67q\>+6=|e]k>OI’3+,#y>2%[XdBm\S]{PP:W]6=}폶X˶ +jszꣻz[MZٓ}=`jLa3;b۱}QܠS 36?qlfTGoej2we_y+ۗ|ʽ c{0QԘUNblj%1c[,:ܽ$%UsTxC6ߌkg.a2ȻMn w)k1{O'~Z0Pst.79s5G^2j|t`ܹBhP~{0aaĽDr{&vAն;.C}:Ks$|Asr16M4i8G%3^.ګsmsK|F =)k 4Ӿlhº?^"v. zggP{J[*Mr+ׄ% p>٢ڡ]h|m㭗.zzrPO|!gzɆUEL}Zrl"97[C~Պ/{R%?8Y&;G<{ш9v=U5?Y'e9` U|Ŀ곐V%-Cᮓo|n՘Xݖ}ov>{q_k(uZhogcm9aw0%k [lx)n.sdǥ>]Nݺ]`mXөު aZ&gKy'S 7'j ܨ ̌辺|ڙO15~̬~Iz{~Ss ;dܰuw pU _h8uIUDމOsj}{*yw+6?? +k徾Y"ijOo<^cUS\xq*'Y⩿Okū/zsլ2q2f,Lүhu/b<5ԚkYb1Y'rXm\{$멳&zm:G FZ~\uw+|N+˛lMY;Ԏ{}<",^?՚ 縝vOʄB[yErݮyӝR%{\{{*.ݙӸ\o;>:sWݎԭ5xݩ}+ϿYks֠'[5'Lͱ\NχmF\wnca +nSV-8,>l9Oe=:z_Ӓ>rOIW#zKɻ[f!SQ9xZ}SN}1]Bi i6 _؍N +H6~3dz *3n$\(Vȩ^wݯvUf/yu}-MN ^Σj0?GBpgGۢ4ٖt{pzy}j[#B/l;8`⤣C\$<必k߂/\n=dӆ \N9,QZ֫2 Mjr?e[L5 Ygy*"q@Y g~'u[kИuʅGBI[{M^fҧj,SJvRu+ kxtSh +fpwOYx\eȺ^P҆%D~xd^-, +8&KpgHd&S_3Kbrw)ߏK*ެ ;]cjۃU5N쨲lx{ŻR[sϦ_AԨ?kHkuؙҗ +:wCE=2ŗ_3|lz}_w& ΛC5Vӡx|Λ* +&d!eQǷy-Iv=O'+s"־ʲLRX:{JkWViV! SαzrW2[Tm8cR}IQ. K+.ٶzfÊ [-c3(߾v#*=q o[}CkAlpb`}Zк.zһU^wھr+~qў*'}\O,2ðqsN|R1K-]UM?^.;ꋋ^2t-W}<9:ب^5?a{Ɏ ~Xf3eĻdmm"B-MDȜiߜ=ukv}~sMyx7L{-9z 2^q)]1e^-^gUz#^?=B;> B(!mUOQ̴G:c8}q馷.gM'-e'2F5RSJnł?͛͹=ޝQ`FѳoDn{X襝".5]E yzV[g&n %ۤZdW׻>~Ҽޠi7EBԴVcPx|mw1G\X:$iŞ'+\՚՟SVyMG}oc\z/~z#(je1>V)/r;J3[]+76wqKneI6gOEXptٟ'}Yg|RRٌ=.Gݑ8Ap~.[ͳ7w~bN OZ;-608u[.<2ՎV^厩 ̏byLZJO]k.rgeȉ?IZz2B/>#iՂsg?y iN6Kd#;+) U޻_qsKn=9}ַ[:x.vňy-jۖ-]!!x\3``xlwףkn6tkȥ9/m|nL){tKwv才N撝"rX,ڿ7'fŨϼ."yҍ]w;_aHNl t(pkv# ŏa)cx =}1WWNYZ s\7rKl~Mێg:^ZaU=U%6X1:%1F~it36$]%7gu-&pT+B/< YV}VT{|^/{LJTϹD;twK,|6[X۽bӘW(mʲ&c,,FFU^\wٞWWT-:|xYq==nc}CkH2 w<nQ͚rvܱ98[TH׌m߻NJ&Sg>̹\ξAxAݻw +6#nm^&oε f>7<LY)96*_p6q jUOlUo5L$z}֑[v)[7^}Sk%fTpI֙ó%r+?S*K +7H=t9)NvoDXMžʭG?k30;WywM7_4euncSJU4iHk?'b;b[l`ȫTd7+0񫽽\Pto'>hcyK6-,zcqf5[7ndu[&AQM[[G+h;-]>ܬ6uѧkE4ۙwYxFfS_4ܳ9G On (O-+/kDI0~Z55i Bϱ{pr{ oݻC^gǔn~jMwrh=Pmnce?8i])lDmvsON=Z2ySU׬՜O r~[}r*O-"f~mDpyfV %[^^$#*>Zkz㏻^XU\ղSIyعb*}o^Nj[ToVY$tYL u-DZ >D'ntWشtb' +/&78cV_AA&'zV'lKxrÄݿir_q:Y}UE{ Maw4`VĔ eš%{bCzjt&fI-_ڽe0xkQæGXNP&,DFdߛq+N]c! v^YM#;-aDt̬yʜw<$/=z~|Ǵ`ܢ#2'?^i?vW4ST}~؄aY&j˳kVXg|*pYފmjzzxF9g2OvdEXse;_xJ%feF'.~rmᡷZO{sK}iHX Rw7^ܵqt+8X +)n MQ)%krcnj2LoE;+ژ.:am*.=X2_^zFo{'rڼ>f|boSfn`hg$Τ1!ޗ{9,gq_ [wg̑_ϪTv}}.s6?Lf`+m?nҿqC!훏66w]>?1sw];=6qO^޿^ZC.gy>ud8a*C&fkQ-ܽsBw8<˶5D(/yBϭVԍos.;/{ ]8#mtU'26=5yKn_g5]l% JR%j +kPE~7t\f%l4_i4K6ɘnW4j?8Jf?3>Z>{ۍiOku=l7v}+{RU%wavgDeq ]ϸ2SD{UU)ߨN(k֛U}&\akOf s3 rt`.)6vv=5,6}A&W#~=S=]YL\rp6D\3Q:УU?Ħmv0(nE}n2kp;賟LW5hֳQh"r{SJ-,KzgbҶ͊l=6#c:ƕM>2ev׌=+Oιg]s_^͡^8A':#/|ɼ#Pg<^;$^e7G{X˨=x۴w4f)K˰ۼ U3.:tEM)5WlՔֻUYl8+΋]힩W`z>`h9 Of + +?8&=+lF3gi͸Aag; ul9OKyKBTzoʝO|d9qR%̺g͎V5]Ge|6-؊Q }1ޘ? 2<1ݐe9I5w^y"q@FrS nT}1{$Y ^[dRS u9NoTPʿql -OhG|[xrVjιu|&OԛUX&4q]gqݛkꦯݼ*_/~!i>!c{gb3sgx01d~dovꓻu=3[\lqnjɟ2;b'بwn'3^ Ԅ%~%o'B +Qz'Yjs2h~4ʅϙ}0gkЖֶEf:|;eZu3 N9ԫ޴,{ں߽~|63>sG^w=JNZ[&Y$B!#bq|>lkysrCQ%oI~F*Nw 8slVէvk1l|e$yײ/t~\g OS7^|4r$eCv)/Zm#c+dzXӖOyT1^tK$ǤܜXWaz3mKD=bS&ۏ,I؂k~SX43muLNJD!j["(ص(EnW^Vn ګKz{・ 8tvYR_ȪۅPz +Ùw͸S=[ˢ7jN!rϒ˚cwd}~R8wӜ?M=R~rﲮz;yUehO>=gZ9kV yNyVqo$53MbtxVcafa~ D7*8v$gۂ-|;LHF.icYj3]U9,Udݺ2 A浠UU_ZX?*+qofYl)+f/ ?6rnTZoѽd+/hɵzy/ޗ7hlVH>q)Pe/λy5缃Ŀ94\.1Q/?8f֫!M~AW޹Le[ΡoT^}%ܗ߰bҚ561; +?|\y¶ݢwefos+{~ roHч1Y.enTPt?P‚߻򞑇Aܟ_:0` 2[\aK+_3CEMcɓlx𸡥f jJܿbL9kɔUǗ +NoLv璫Ou gk,bu/9q='{U2A6]ƞk|4wJʊΗrz4~q%٨ ۮw΁}?Uy扺Q{t˻9+_߸®=ArOB{8kƲ{MJǶض^z0HPqӿȬ3*~Itn]ؤ*h_ +S8mn˰+~-VGZ\_]wdNجG]Bʵ듎ԗ씒9~Q~sercL+Č/ggܤ=  Q"Oۯa2_̺Ϋ^PdV7۔Z)͹YktciMLvi\7]ٵKt헮i:jj:x~|}nygawTƏ/T.1=l}wh9׌lۙ~jKde$n.l/׊!b>3526X*JN~Rw'-7o9R+\1e퍟2ykqmո%2wqpkc%#Xgq1ilOYNԮ.RbE˫gIXuF~r W'"o+d^gṬm3kv_~İbƣoUY>]v`a8u˵Nf^S7qe{<<_oǣ.Ob+ە>Wz-7{{6j+&^ל4ϩmoͷ3 I2:Ad!_odorYIsyWҐyy^ aEo/g1ͮtO>|=cS>4*~tk=\{ |!ow}~MQ~\|9BMGtZ^;5_9>5=ĒϞ+(ԥLRV{AgSXr?^]+3gc/j]?m+ٔJw]{o1ɢ]^ջlŠ_Ο/cͤ*dZi!aK6\ZVoew'6(i1=RIr%?'7$'ۗYJ0z`ʗyiHK2u~vOHey-7&y|~Vheό[=p={H۫s'V\qyJ+YS轮5rᱩ'**'M0[|U/;dhknp|~-/8~ϩcΛ|?衒Yi}J~lYs_RI}^촹͹ +|<휼Du7Շ|' vH~yaD<ط8T\ue7>q\?'xߚrO*ca٠볫*CY(ΖRŞ9g_kw6Wa.'k?׹VUPڝV◔NĉWMDŷ~9v;֦g8 Km2[s> [Đ`qUU=fѡ8/9g?~匇vܮ :{+.3E= s氌M׸uͦ51R"OMgU9?cCj~zR#6~s z/컱oMnX՝O_uvtO/åPIơYx-'K +jrcnΎVוy lJV_/uRE:_?.cW'NN㓾'{ĥA +g|tQ""Tj{ϖZ^;&ftr90%lmg?R~;a/3YJ. +\kɏ\wĈs=2u݉Ň32kWkVx4Iem֟vn%/3wrx$c7<撖5פ zZIT=rMsfz.#7pߵMή%౭~yWu龹%)vF sKբ} +5RKا]s'D'T {[O<W?W^<AǧDUy^/|Tb̼4b7I拿 +}w?{bRtϿ }-tPZ%ؘ*w+_~zU'TlHt`932'o'wlI~vװҶ]ߙ.O]櫯f>|Oa{{{~쯎281jrMa|y? 8̸~~*'/Le]ha{5%?XnѺteC\̍}Yȳ~k=PxsFEi}Jw73l0 n%wsgW/Tuz/xӗ"^Yq+/4図潬0WZ`au)oo77de{.y%x_{69tzǽR5p-ïÓW|6y1aW + v{y LwSw)sQ=ryIy (?f\_ZgE 1,oJ?\7}EFxt}{C/e/\6AJ?vw iXyos:'xmpIjZbs+[y?*T?(o˅~^|ɥT>kΒAkVsƮܾ瓅&͢5?Uu3rJՒQ5'*3}=y˲~x4kM-K{9Mviq'oa 7Z*Mݚ|!ѡzNe5WZ.V:7~(sح)5FƫoK.Kr3ע+_5?wxݥEێܻ)"nO~%=Abkۮ'N)|k+t~ Ru=_/#&nCwYqEd+^ߦI.~+4L8yttcsUPԹS胃uSTi}q]ޘ6UzLk'l˖kYіkeERLy vZKsM:]u^8Χ+qm٫ۛ+ΐ{ ڨ;J:c#Dۓ7!?1XK`N^^.?/ݾBŜIc0{s\o3.[cG/sӷ mɿ}J z>~ޔl#ê٫]p-M+ ̓Xi.t]I׍5g/5cǮMr6|"rZ%*L~n<ey+1d:\Nm;Dyr~csz6U47Yؼ{POs;M_h/p A.̚|%{Ed`N֦9kfI|W^ؚ!x'S$S>cH3QҙXT0NnApUO/0?.H j=vK*`7o?͜eYB͊;^+yLx6Gaʓ{-&G|, +:>s&7х D~`GM k_vdu-Ͽ+6}ER7r+.s.Wrh2 +9wE&:f\Teurg֥U #ėH}K?dgTJOeqA7}{ty\ HDt ;\:?V/%mܪ{S',%1q9I]Z +#?w)bnٲ:O̘ o?f`zYo]"?(:Sjy/2{lhڨYKsYĦ{~REǀU{O.W\Ϲ~7]u]nfeIMYk{`Ew&o$RdM'OV~u,{.,%E`ֶM]q׽jV{-Bm?>-dw9@Nd4Ӑƒ,_N)ш8ʹo)v:u'(eە3˃fŖ31kӇE"O{7ū"띝&O9lHp0oO[ƶfKwzLwӴ+[X~y}ce;ȻgLo5mgXxٜ0W˝gN\9gcٞ:S)qJ"й o)vVؓ}NTzt+=|?WZYCQ<8_fkJxo:yZCQs+YCm:.kr۴JPӨI 78NZ}<}i4No55yvqƢ-퓋=?`uQg%x~]JQ5Lu^۷;Kldn6{M?:n1urwUAox^8t馫c'1=]y.7\.K:>o[!u9~;p+ڂͰT=+3gI9Wy-cʱbL+^˕^cslgs2sGf7Uھ~/?lJ{Sw}t`4/YYvvLV~vN'/uٯmlyG-[ƊZ7H2yb͡-[YVԴȫ^2W^E}_d?3-8wo{C~+TX١ M{pC;&~hy{juk_/]y|9W9!#a q y凓&bݼY=.FY>uLJ,:\Km;q OBj>9t2{-νЫُl`xaC'<{q~_>Z9Igq'L\r=wE2Br[2fޖmpHJE}:&Ŧ>YUL`7{E8Q[wJ7,Xt\I3 s hU-ʇlSkҹRI:ݤ;|5/09,5x^qbÅGr//{Zt᥹6vb`vDj[+ۺ[<wl~uguneTowmvzp_mhݩE+urr{Ul丱!aM~ c4xw${Tli)|4wA< +s+,Ha/s|…9ܦǷ>)JޝkTClB٦J6v1Pͺi+ߜ] Nn/|^UNj]JKEbGHpLo=g6;oնU"z$!{9cnחgJ?964na - 4k{;tK[~Ӹ崇㎒M|7n>AߎCaDžO{D.7Obn,\n<\鎿3Pm g8PzkV!?s^CGW%U~nBTٮPGݍM\͒u_.$j,a~+Xkޜ&™Uٟ Iz!w~Z '~n>mb=B,2埢;ܷȮNeJC1G7]y5JNsBV=б藵$Α/ DKiƒXkFEvmv7Dy ,"'ݷb'o^_^iX}I̼-) ^ oԂ'ųTP6fM4x4R*Reϫ1wc#_γ%~s¾/ExguGxiSR+T>{p/~<:J2M\% 4̱}"@iw%/?OwR;i-wX8j},h{zu{x +aeQcj+Im9\kՍ[[s'fmpa~$pﭤs۟eڵo30]bzzڕtT~i[O\_C<+~-x*ө%5K>R^hw_DؚZIo](z`{?~<bNGD*Yo͙k$ܹYD/ ׏ۇt|s|ޞ ͉W~)Wwvg(Żғdi 0{ +N<{顦"H"ŏc]g^vᩈ]2K:{; [}i 5λjDY~ܮb鼖W [fow~aI'Nc |J՗_Nؙ.LZd4K˙x6<.^=c\Ʌ~K9SƖ6$$>oV gc䎹ܢMVN(qдK.^3>apO?~v'nc;w]`nh=7^^xڳt׼vOu-fO֙Ӯ;ln:cFgy,69fzli9T<6?W]y  ;"uo~MSO=x}_$ݩdK֬7iqϚU9CoMr3ΔL~U҇m2Iy]۾W?ק4۱qGd\oK/Kas OGF>{.5z\/7J=2I0`ܹqF/͘0׍2NƼ<b2O ~s6BU[.=^w;_䉨[x^cϣq}KZ|?wjH?v}Yʔ3RV P}$ZxeZjyAw ='y +͆|$Ҋ,+s_p}MU'ՏV,ݦUw߻O +5ye쁄Ne651:I+n Z(}JG+,"Q8F姮Nc5/m-s] &lW+43bWp;XOGq˗_;_``}kD<*_fKNzzl\sj_GjV|9gYTʖ/neE^HBţ*UCC&8uiʘGI?( #r9̻5h꽂|w%col3_ۺIY\$&8*7'M!|RٿwnC%L8mwvr)w +*ƉW8xC;JJ5?/߼I7fyJqɭ?~`Qh@ܝ3߸LJ(̜Ւ_cV/umWߒ-ycߏ׼VVd 6n񬹺0Ng串|&^hȶy:YC~3ub9gk_ǯlw"7$.\H9`p&4Qǿ[5Mgxpl[rlϧB'o9r`OO=n~|u?Ŏ큋&ܵ,6lYlLE%M3>8PqalNMr}}Í3 jEɋS,YV,~2|K'~{v/h˞qI'̶.8"w_!&..)ڝcU//n]}$l-drn Ω |ӣqŜ!Y\[L.ut:ogd+*3݉=9WLz}Nv2guJ zzMϣ3|Ջv.Ͱ42?=Fz/"/aX\Kˌ,׆YqjjTy7V|yc1i;'<{{pWK9_>|}SɃ)KVr5&td{d%-~p%gUϯ1`p)_f W \X4eT`?g9ԓO%I~阸^ 8SctKj9v40fh'?*V6X!ot{'~f|wNIU/U=.yÖ&gKevR3D޻oA[Q]_/sS 6ZTvo,|IVEXud,M.M\guIkޑMGgFv +.X}4CQM/~i;i+Gqz2=|w{Iݿ;gͳ +‹ڶQ>:r4egq:9y?zԩ5*/;4X72Is3boze爧Q'_t]+՟Y/=*Y/+WE /.:sS[svkL毟LgxS lg-g[y&v>%/5>vtnaK#:)sv,U~fյћs2N˂v.T+.Rb}\h>fl3cm3k&-X7EU9e!u*OKt:X3ӏ R![+lT #Yßee +Ϙ#XVMҽڥ}ܹrJ@@;Ϥוt)y@P}S9%gbۼm]Y+l;B^XqO'*e+Ss}zs2x7n'B.ZuԱMŹێ,t_vЋUSy=ͣ}kYI?bZ6WOn/J'W r' +=GͧFϧ3Djhh:u#Ry}b\Tҏ.ֿ]3 OKTUR ' +r?H9.\[ǽC^ߝkSnz詷~!:Κ5<9ak}CuCMWYTzpj)%_i +|y4soyė~{ƃOjB‚Mi?9zR ?e7mW,f_ޖqf~Tmfi_f>?LZӢnl\N˩Nf 2_M`f<ŭ%/ucA7[˲WI]97{jk?-].c͸wY%ӹ[ZKVOewemFċ&niWB lMpwl}ӛgo/,\x}1^\^6:TNng ?~Q~g3wWݶ^TkZ}ޓ_9B]9c{nrN톀@߸ v\TQJ +5|w3w{8yw7/MZdOזW +g.^塳RjwZd9ߕYU/d,|_`n{E[og7&&l\j/av@T$ם}W m\SH!u̙G|u#%8wf@Sw%\k02+qRC͖ԙavk: *슛^|K9O7k:T0J)ZbVx(\FIߩ)U]{¾ %hKלss-?/Z?o7Uhy6ߝsWi}إjl 6=^9[uȕzt #=e뛻[^g;QT F+ߙ߷%nJ>o }.L:?c⏯W̎{7$S_dޛǬ0W-vzոs:Kf~޻Ls>:0kSmIgo?{sOm R6>`Bp3gkZKX^(b09IU :%gL& I +J\+mu|NZ/VCIK;O޹(;艛\&oOJyyfo w%Ko?/alٶߋߖ腹lX8gƪ܀WִMџ0#QRx{ummV{R}~Jk934am*=c41ϸYS8m yO,YeS뗮PntDoݣJj1)2-޴!>CeǪg<Տҏ{i< U*zKLtwf]o|.Mz2Uf.62Qt5V}^u4-$y/%'?rtjOL灇r[ǒީfW_d1ھ_sƄGLP)SrUA ?о>3eķ<sZOP=gPmzjMv/n[>Oufwa{2WXlf/&3o0kAVDD\凿똋JK[Zf]Rw=^%jy1:{;{Usxҽow_m+2A/}tM=Z8}eg_ힹt\ǗSb7 +5]:F)9/s/LvbKo3iqL:P=ݟ N]\=FX{} ;Eet|4OjsJ3pPJ';_| L|zۏGeErg݉OUP-ftS:oRh UˢڸFBM%9W0ό`ܷgCU&+չ+ׅbun`g=K)k$;{=?<)5Fy/d!;Kl"3eo̲O^-wLnު i +3l9z݂O +5TzfyosO?-m__b]]9:_񺛠Tr#w_ ^3k̗F.Mj>U<]]w[5>M~F*:&r~wdqQ,V{c W•Os=/_\%Lz⛮|tn%v SSOXʜEOj{qBh[?;k‘ Z"zVܜwy)*5*Uɩ/&rԄ /9\N$Δ$efg):/p.28,nyNV #5YyGf-~{>˯Wm;2uYSX`e-kTV>Y*7rrofZSq[6w/n5]M 1;r=\? F.S|8{nJR ߛ,mh${l>? +̝&{^U~2&3E'[c[.1ljkv'g/z~ǁ՟<ut\ͮO^ +/60N_crlυ *,RQpζ:v&/9⵮KJl7_7r)5F?kTNYbﮧ}){k% [-:mϏ÷c~y2OԼU˞Z`;%{ݚTs*~}#o?,q ouGs|ɔѽeՌ߽Ћ۪q[\۟^⁥ή<:fk.uRgo&l$%\&\LlwUSlڶI}8jl!yUk%iM^y$yqmMOƨM n~LկM}yK>Ri{ +uJm,z?P#FͿ3+/^mgR)zNoY/֭;tE#%k/s?u~⻩&Eq8e.wؔ,tG_{}yީ=iט^>)k tp|znB!W-$8̢{ g>\T[tv& +^ -fȰfy!F_>oC쓏#ϸvoʃ\7Iܿ6ﴪ( 6,[9ߥ\T?CZ-{|%,wnw0ofS%839m9OwelLﷅgn҈Y(SMr5 ə$r{nnz1ޅot]s^6{#öuSœ~aQp0yM]tn[L܂W +|viϕuD>q/ƕ':,hy^^^^Dd5y֬ouUXg{xHNAѷg E,gnhb|U쑮#s_4 ;ǟ>K߉7s76=Uݿɟl_\js)DAl޵8,?M~:h<0{"ח,mW +*㗹_UeCQI|u^)X5TKowO =OE-˒fIFTA`c끽{l>^AɱdC+o4xy.8)s}"/13` r6JO\ԗ8<5?_Ue6qbE'5;R$%L_§GJoFɧ>ƇXƷ/犯wY]!Ǽt5Cjfm_2tKޔ". 풝C-b=/T*}-\S!6-8*LJC>KW'߭f|QbHU>;FI9MWrU'b_Eos +->a$)_/QZij־;evQ鶚s O -/{ۣuj>wEPyj͜uT[˗l$dغ=y}8OV"p,4^T C3EtE~Yyk/N1A 7oAgg}SǿWk_]5I) EGV3ڬQwOe + _2?N+q#N~uGح߿&*APyKQfct3 +32-J I]=։Z.DZfٳw}Zv_Ƨ+3(}|yʛE9oE(8^p@?%2n-usWbI +ݿО"afz-%b)k?)GNyaǩfo[wJ4bfO JJצ & ;cս +ɳ}7,A?~ +IyV0~l5Dա \ Bv,8X~A_.[q*ͪۺes"Y-_ngЫ׵\S4lvM‚7~ ~6kʫn&37/49Z7?3*t^fJ~^:k}|}өCQOؤ;ɷGN5$=alҝ3C%JJ_LNsņέO[#%+ɦf^kAZ_ejo9:}/??*:ûԶLkzu[un{r߶ff9lMxm7{E8sZ2|4Ye7yk3[3h~JeVw{ _NNL|tM碣n3' YS~Ĝ3!_ 2C5 ͤN3e~[}HಌϴJ *elXL?φ]+4 xqF!kt {gjɟ}JXvǤЕnH|h9l%_Et0DMu3R_7YY7#piY~8VsYn{ViO퉶*Zs|+'#d_~}ᩊ'%.~h/YĽ4 it,t:G>94?K(Oqx'Uz8#tZbKVܞ7V=wY_}=)G4}Vϐ Uc沓w>6?r¹Rݥscw(P^۷iRdLߥsSrAGJtäUT $nbwWԳWD~Lʾ“Aw]i ᾰ۾{toՉ 4g?~U&abd6>to N;QM3th7&Šaڠsyrqa] YzpMm&8{K庼nީR|zFYTͿ5upfo@U~gz?/EUӧ[矤7}ŋ-og] ާswɴ 5IN;MzTg#esΖ˭3)=2[tNH. kNE}/LbUtMj=s$M 6?vyC:&Nʾv'I}cӳILүؼ6qғ\_,;Hjű%q~zk{DUZwc9.<:U*u&{ܝ~*)}j}?#|KV\~N1Wo\=>f=y#fl/wz$ekN7EK~ yUgB%iL5ZP:Ήulo|ʊmukn7_lx3W|3йS^KBr2 ]g^ +4^$,z߼BC%to1*xoZE7?>93f A7tɷK80[HRzTqf]m^:er^z~?s[m_ٛ<ǿͻE֧~S_4Y@akkĊww}|>R޳z7iުtI VΟa<'Ӌ$+'.;.e.2!kܞ#lcTr\>{}O[]&xfOeQzA˒\n:eߤ̵ũ*3"vw|蕚a#e{868gU,?8kR_{U?Qfd'WվL:7/ٙK/U jdLyhת<^['͌^T4'@*h$}WWq>=W~G:8*^z8×걞Vl\US E_gL]7c.IrO$c#{/|?@3-ƕ7or:<<+ |W䝔,Q>G?Eխf[g@4^˼>sMbjߞ>mɝ4"4e];\?BD#X_h޸V-}ޞffE+ +LWh.#tyϦQnL" &cK+Z窱wGN: +;oΪ룼C/ +1'L}bAL/#~98mXsgS w7)gXpJZ#]Мϟf?]lyu[J?䘫>-dPfϳCKͲniz^o…WGNگ?\N.?m& td I.gp&A>BAbD䲨(v;SK5b:]oҴ9Q8O8t`Y5?d;0)38;*(}b+ag +2)e3e8?ae5L`l0y y['ISytzcޅwgo<*3Ŷp]s.,!LQq)Y "/,*:t]toyLhZoҍwlX?ELYcXɎϞ}5uRVܳLɧo^՛g:eLVw:潼_<2={ϩeUly{7Y*lK[cxe᜞eǓͫWvq]MyK&>Ypֽ[#V@ϗεd9QEݱ-YwSb}RI;lò?W4.-sfܞA_K:g4aم*.d~;oi;P7mGnLx~ͱ]r狿MJ|_%,*aۂ/ZRwhWM~`W}`[]Sx.Ҙr$ JqŇO;%p`usW*>t-ϱʢ4&F72˂_%5}̊~%ā GVEMc+$f2[)-UُzWixK`691=lxRįSTtiyƼ"ul 29ڄZ+f[Ph#^4#'Սww0Vqiɭp~8ZǀgTݳAA2ϛ~%S@=WRs7]<8.[s'OUސՔCNGz=3N~/wjܝ| vY_ݺ{fl -T}8afҵ?Q"ӌIU wѦ%u5 ^?ͼ켪ygoa`"_&uOf)ٺ0-iq\́_野wy(Vfxܳ"'M j'^dYPqFc <>h93%S-5ۋĵ7=4Ey,S56y+eĞnwh t˿+&i3m`CNIf͌κo~[0i74*? rb+lmf͜svnNQg^cdweV剟?8<[R[u'>MMmpZ{S^/4f?} +_͹⇊ئjڶ{ӛOo:ޤ+Fa[\ٯr/r_omЬ78.Zsij2_Y2;/U_x}_KúfEvDGԴMrؔ2esW4h/Z*ujbӼX9?>9uє ʬ[R&/Y)ooϳv\>kn8›6uՊN-8̚m 4wptJv=jm]~*γl폺O~;ӝn?3n?{Nd6cɣ(\L ϔ< I:/뜏Z- -bB^Y=S8\pݵg>k0ȭ.Ozdļ:< ޷uxDOHgE3yY/w+Ol$,x|kWˡ_\׍Nqktw{3y)=owhR )'Y̐PhQYcYX+6ǖuku-z;dVWιNj$eh"wI6U?ē5GMk7y]Խ^d]Ǵ:d}X]濂 .7hK_n\ E[־_v"~z󦡺s۩ՎwBFRS_F8V&Ѿ 9ӟ,S䁋?ۿVXӐ?瓝 e>MX+O%i:3O[Eګ\X;`ͯtL9*B.;hRkГFQOoeX:s&&MbK=i:wDӧE,iAEkIwsϗ&~HYXWFU 7[o/uuۗ[Ĭe~TpUlŘ.ďg=AnOxvtlV[˻uȘ>Il'҆uK+9 /,(vv:bupmG + +%>m99AsdȬ2)cV7͉eQO%^^(h]tWNKZ\j2<]&*C}YjRTTuqڿ fOH_-ê^"8-Z?J}}U-/Ma,asg(ӺQ[WpZyucJ\β=ԫbDvgG:6zfys{W>O-Xpz_TL=4k򷫙oHiްAcm+[w:,ef~ÇSO 'wgzRO&gX8CӺ\|<ӡǿYtIGC٥ dWel8ˀ/:II"+;+C?%2X3wx_I''o͹eLamn|(_XuUv ڏbۙkE{>QBjn2F~\}a++?w]11|^ۜ|bsG[ϥ!;-SIgMSV/u4& <=.^TRq䒋$tr]ۧ|v;*RUm_ciryic̓yªZ}[j W=RvGN%'mG{zY[$1KWߗ%*ܗ?b7aouޟvr u\vc;yR_ +~:_E){3bS*/OWŪ~)v~vnѻ8SD_Y֓zwߟܕ7o1z3h^ήJ;_ڡqǢOMMz/wm묷 Qq̧GOirj^zBi_2Y|OﺼwVon=V u㋒I3?z9מuwH ItYxɵiEf\n&a' +^- ϴb(tޟ WIt=ۂNk7gub hz3bX$Gۋוhnǯ/ۋ.ڳ2{+~}ޛ!ڐ ?]v[ئJ8aFĹyr~S٨ؠPaZF5G>]SQKgR|􃃩Э\vʳy`욭>aهe/ } 8eI>Qm\ĨA̲-'4ڻsmڭG:=Ȏgq8u_TW7=CμVǜ䛞lnT7ٶ;46ήU4;Em턬g|~;+`,5dW`- ]Xj[<-g3_[ KE{W c;wk?g>OtI sSʄZ;>|qJz^z]DG=-y[ι 8Ơ[P_V.kM%=L+N_P8?]OI +۸xP kzYWuUUJݒ j,pw +nHDO#AKY+cr㵲EOu[V\]ibZ7UJ/w%xZOc}UWL(0+JO#~k[ ?ss-qsß˓e=RJm&v~N(v۸޷,iEw$ԹB׼kUhg=WmOּۿʣFe:/wO2dڜЮx}Mw#kњ.iKk= +<0?p2v*l'"=2UpviOfkt;=gCnU/&^p9If_kj#õ,ͺ}˒?U+{얌]W򳞵f:Qғ]WZ,$z[`$ +3͜Xa[ )3ޖw*WmeWL-cq~';HKzsoJZuB\#?8ħlWfh\ +%^ޱuK'e6}O[ەʖew<\J97iwnvʴMn%7/xfww޹(SIUiݟVKgc60p(wɗg$uw&stzyɗ}g֧]{yRR:~sz# ZgV}X)G.QQѓ" \\82גsbl=Y,rs(}Ӷ|Ǿ?d}9N \hӳۣϽ,qwy=[]{%:9dI\%%wmsyŇ 5g&>lr|ǜً?I,n3s_Vܲ%SJad̢oq0.g YJ^W'}isw31#6Oy7imu&zrzG#W_Iz{峭&+zeػ\*+?mZ1mFeﲓη +>v:cdi_K(rW/h|/WL<3քqܬŨ~1.?7]Z䳶JeL+ ϳl:= -F_}q;S+ ++ܞR}ċ6c!KRdOlst^~EObD+z/t0tvϏ\R|wˏPZ F f{Oqqg<ŹdNFkzTV5TyFKũl]Iˬf26uo/5Vњ6+l‰mo㸜>K.;uGW?Gg[떺̻'&޻D$CcBackp࿙y1KaY,|6ݎj9,<|E7S ʏ ?6N^7חE&!vֶDtX)]X[˝nj6 O꣩sLM[qmn=zשwSncMqEF׳lsUK +t3~r A ]g%^\zѿj[u~9Df +u9lJ> }z\ߩF6Un~֧ѿkftLY)?]9*)m+^j{4.aqҖ.Nۿu4K[ttjLʴB[+f믿9;vJ׷gmz#86xя{m|c]͙v3e&ӛ%]pCN<}׵z-w,q Dp?VL`W7Bm07opLW]_UDNayILP%&cu)rUOJo?ؚAQvE6nw۴8dJHyL֑n\MWN5åɏ}^v` gwRSC'~SmؒCHt_} ].7]sֺZ#.fVE(?Kd~V>Nz vz_^{Jk2MT+86[9!JζoKt|/VrYqol7~YmʖYrq ړn3GQձX+MiW W=~q>i+GX\q+_KXUθf$469Ll/TRw˴9wb7ǃo$9umWe,۽HCIvm|uYeUlk*3{'.ɶ7r7zMKC-Nj:q#j`)]}iOHUq<VH 詾1gwjZD%36+L4\΃K E#Sr{%߱<l&>p%v6疒6 KRjoxRh^kp_֑UyDyaKWˮVq㽆;G_&v -TN+>sB}CCKoUش@3y7ח0>JXg\xN`gnȟ?+zp:_S=׿xY[׽JE節6)â'oWnLtIݻ2+4^^YYÞYG[g\ +WyPcZ9mKey藜]~`pĊ׹fzv)J5&DžUYp;NRew7*Yv9^qWɋہM~8cnml {AopҫmLt9Yq\SU.{+,7O?M Qw +U +ZggAǟ^=^9lef )ɳqVT6gd߹ŶΩ; +8m˧F)UDy|>o>^ېDߺEOf۞-'Ǫ'o@Mݒum^ff/9^=j]Y:iyƅ +\9s/Wh͒7._^"К•M T|("Wן9=5mjQ߷VYzh~3owpOٰPR$D(:sGt@Yջ.VHnr~ mo]ej?=knym+{3ne ۶=.j]sfMtpƴ@s /rgw!gaϛ%IDc8tv\y8*/H[~ŠUvY]-ģrso\m%3ޓvދRس+n1~/ݝwX*1_-fǼ9kD5owۧ_.WeOL8F7r:Q~lUQzM[yeHaNM^\{PGkck^3J)ݤ?AשI:p29/3Kkgmbi Zmi,=?-Y+}ʇU+|B[({RAckt.~ސ s9s xe3M&xL2_~!xm̸.>\ O}Q |EHҫGB ᾫ1{Sl*ר375Νퟝwi]6kCEYv q?W΂ڬ g^\::6r;6n6K*:R7L +Pim]<^W,} wɔ9c/͵^[YDt/jsV/a襶as;O)\nUnLRwu6 [B/ yS3ϰ/d=7ָoOs-9ssIZmso}AZCL S4X3Of-o J_>!G78g]ؤ%r;oIo׻7Y4}{zUv׸S769tӛHdg]uIk&\J53bW^v:76"j{]ϟ]UAiY;&_<>'ϒ\e|weZ%%ʑG;E3knN) zΣozӮF58qqU>1df}= Ao澽'7%/ؔ$/97; >QI6mfj~(.Q~ɞ͟HEot.Vf+ݮujUIykziX`UWP{M|гHKVgO}Ow~KWXVdtM N3.y/;ūY__aӁN|+!!6uzyZx˝,\L|}IiKKOm~L۟ڻ?XP(ۤ{s_Qn+[QŒ|BV+~qW41I2G6|yćm =+'hظG5?{}K7]z;I4zfxʛKrc_dR<3/؞ܹiΔK9Nl<5>fWme4>݂ÉCʺ jVbiEqsulg譄ſJ,]~f}rpb%ӸA[簿Y_V8jXhԱ,+gB弄i=s^m`!ywV6UvmRMOVЮ.bߎ 1;7?bAZ5dgfR"rw\KOd,Xkig*s.G*+JOwj{wyMEd/Ny:V:}*sKn +Hl+=Q\meg5͟vHXp盄rY1u-7{Q^$̗6cڄ?rr-e,;TݶiOuEυL=)OڵK(͌;,f_vU[z'RgQ4iQCjF[6cU2]> )n(znʛGkv~v+}olJ,z #TdjUL3̘p+~gyp!|e{C̚e_xv;o +fHf.RJ[h[}yc-\r˂t +^W<{3&+TW{FLcȽ'Os7矚wF碿:&5wڨ Lt@U=yv rYx{1l:kB{ /,8#%RK;wK}+7{!>nXlsz>$\͵+8Z|X9g6ӎ$t5SIo|qU "z^'t24yl0LpS$RqQ fi +v$)wOY=z\Ud#ИKVIrw/Q:ASR]~7'Aᆳ]%<+GT.w.fL/Wj<_ғ}vz, OVZuU|kRiN3x+nAo_:77z]L|\-etWh>:Rn0F+iNGXϗk(,~:vDc7~_o0OT0YE16㕊OdNx7ʚ[unmzz_ܪM}aBVy>ܣ lpUE.;V-ooe<k6}ݰImdX{V +s)}}W}eX̥opIB Y"fcD۳Gn[s˙Uoؿ~}47UU6AKln߃C{D^Z^bAErN%,][7s[+M$٥4kH=9F$#g U3Z s|cK7x"7aO^Iᵰ׵e'4f%spyݻ 9v) +Is{۟:=ܶ}¯=~n3]"|rJ%gq̪smTضPnO:\?蹥mzs^ <ȩc%,k6hO5/~#UE;e{Z^m܍ ?^' "8c +ott-hVZ%U[Xr]J5?_.j6N{' <:2] +poK_V౛%Gz ]Ic\َɍixJxH`]i0cCK/|^Mc6s"Pyn~t/3Zzˎ*~Ta@^9Mw=rTd[o]5v}X g"uʕڏ~Tgİf74Z +:$)`MEk~]dU|3>8($I~mclqJIZ_lɗVwΒ Tn>]sco)U1W]+~\uv]oڬnH:MCb7^Mb_ZTv0(1?"o<_\[iNCPUϟ +LEC7wi]l 6Z^߮pHWfǃiR/KtO/ծvgEͺk%.Le7.pK])/]}_M_D8vMHrvS'Ϗgf#$5[NJ6y+z9mς4 .jJ>QauJLef}nVc]-s]@8O<'kל\u/{R=?d7;xGsvJJؚC;\~_jעa1z_l/`z4apfb +)Rx7pmkp6 3};8=!%߉M>V ӗ6LNto-GB<p|U)EnlIlju/VQ:5Nlz<ۘz_OE+4l{M^ƥun00iϡUGn4Y3UK(:`lobҌ?MaUU_+gmڧpHџÖl,oTtdIќ^/}?eSܞ[}ENg\ +U r&fTWYE(|ݍ-|<Z`#@zc'n-jFaסbKbKfaӜX}ײ|6)\+2*f{6=ff7;H)m]ss߼yg{@Tuog=ꜼW-ձl͏>k)sofgly{a {^|]6W8=n:9}Ng;孳m]a4 Xm7|F?Έ5Pnu}b^j{+CLcv^-z%aӤSm ~;]6ĝ e<:rggWǯ=UOʋ.a\}=nh.ߙzpkę6zo[嫷>Z' cn%k_Ь9:e*[65lxἀ,i%W&.ڽPͭ]4^_|^c,6xtwòCϢXGz9}jW:u4U$a٩ 7g;}d~MUglڐȍT^ϟoϛPb^)Vc!:4Ǯk׬[汲 MV*.:8Ra]w7Tس wWد?\(|1Z姒qu17ne))cߴ~YUNx`|cDǼqan}Z敞o8+t=Z1=gaW&#|lE;9|k~'%NܼcѥA/;\luo?}rw1mLKl_K\QaM-V,hU[%7כ^(OY=D\;">[6S+sZҷ=w6m|I㇤FbV%N:qEl\旅\z7/ ó,Iؗ.%Al .i yzOy 5ۙ"[mb0z>t +f[hnIp@նc/?[/ bɎ͑qB[ѸkqN;1eO"HL'?ơHɾkf\q9;sc]?%".;ev:+ȟ5[1#rM&?b߼דGnSnsߘOKOCiMKWvcYa\See_kna?oy.{>gS\6C^`i\Yjz.,bFOKl$ʫ pwEv)S={xo7.%;8N]{, &+-:Jɫ1lE-j5c^Se괬,eEOu˔ ܻ1EӵmC;&}{0Jw7.\=sL4C9-엕zúN}χlֲ~em1ˌKx۵w߄*W>.IJ}EM|Y vɚ(LՏެZ|JQ$7f}iW^H|F R\yhtT43~10t)NW8[VMfshJ糦2!{@o%?Z+guy[^ѕ.R\XwD8=VлnYH.$&\QM_S۲Ŝ +"} ^b"}-~./y] ۖw rv'[Mآzkt@\UKVڂw/vVkzUX_4:xmϭs~]ᚢ/a7vVkOg>w徎 OeX `pl=GG(qg +[">I\z[`IN;S~1R 3Xj/&%ef:<^L\%dhS +.v֞[h [%V5;V~nm'_W7'O5Br]sku<ֿSǞgJrFo& ?<̑ӡsX?,$_L׬/gZю3pz-ky2W)ݺ|ܐ&&1%3&d,!>N=YϝX~r{FpN},LWs al ++9e,4VfbZvFn9ۃW2V3/ V7jnoR[&<x=$(A;egOY"XbK҉K53wM<&j(iI:[u7>}u-}'ŝoZYs}z-k_GgQ|;Fb֖] +Vqjws,ϼڧ '>zUՖ?VXctVk{.f9sN>7w}=ʶtm='Kby^> G>=f\"-5ᒰ=%/Wɴ=.|7'>W,Xr+$7L|} ^--jt|1aƴf|0y{GtǦv z{՛JDLI8 +I?2k +QO__{R雰=j6-\dF…wU",;=*bn^e|:KKy5bۧ.-,!QOEpŜ*mUq]/gUm%sUQ~[YNJICx6T0yX3}iN$oTZ*'ӸnNP:!=KݼHTSA/<㻯HUFύ}x"əT/~G,R,Uۘ7yӋ1>ү;qk[Gw+tm+G%Y +I./8/nsdRȶS!'\5a'YL[|?EԽ"s5Ws}g\S[u$`V/޷좋'օs?wj uGΛ^{`"ZTq>S8Hhw{oĔt$R{ 6_^L(\bb{w1,|nXƇ'YqI讈jqR\vY˫)]S('.(axV(fQ1}B {fKJ([Y'̗Q٧rviFLyӚE}:r"z~ul{|iG->]IR7v(c3맍 &+Tx˟~a1\n}?mBLl13m]}il\ֻQRNr kXEZW]P{0{z;! +.yZT({IStT#XZ(0W54SG~뼙q1>MK3x' ZϚ`'Y욙m9E-=;_oh%+MټfY)Wc5T>_}z7Sc+ +_9.$ ba{zx⦪ bu[_FNtTjO%yb?^Η[J;w>>gm[?Y.~JhŹ )_Ŀ_qkJ@ׂr\Z) EV/佶;3|Slfoix ڼTzS[ͥ7ۨxFdKU?Z,J9`Nٛm}e/ "2`aR:ǭGΙk,=cQ?ʾ+mz?dMk5~;큨O߿Mk + +ܦM4]O%|qއKK;5D\xZy{Z\lg#5y/lhf 'y_c"`y5zկI }|ne)|(r1^{ybNJwn㢚J{K gcijc'bg>$ˊ-,>ﶬ][\"۲k̋ny3f.>ݒ3\ryWOċ訵Hx=h}cg7} +Jm?wF |m.'6gLP_%?=s~ƻL0W*jt-rLoq/ڄ&$)Mx}-?HbƏ3Mylō:w:<:;lWt EyZc9nOoVzv֞wܯ+pxJ"ۚ{yIb+qp(`Uhcv'CU[76ɯ}Wch[;kҹ[;Ϫy^v|k9\dThz&SN%,?5-5da$M)+&˱KmXR2'Y~[۶?f:<66^lvڷcʣśfu߯]9eTєSsrU/-6T. +\f<5̱r_|L9-s hW)tP95oRU?W&zPI ƨ_0x"Z_#6\Ю8MrC6/Oifzͪ|Ue.͐'Szm`ЫRؓ[~?˙<bH_k{8~TJzڳZ7h˺nlEӦv/#kl|qd<&}sAog=x?GzL:~sP/柍ԃql:2EfsV߱eQ?1?}Dû&jSZs~Zk<r00zOU6n6jP8?YHP2:AÒX"Vt KJ79yqHqZLXpjI%U&y+뫰ӆ-) _ȟ8<+}#M{-쯊]K I[w|\ŝ37[,&=3Oo f;jʕ +^{CZO73,|Om4yzz3ϧ"sOnXvY۶ys֦HO/GV?eW]Qrp`) ߴ~sԝ#>uW*&J +т<~]_d}!˶!CߥwEo<ݼrgK +5FPѫYj11ߺs/s@ZZ;N m~ӓonlrS@uIs$Lh\&oz-Fn+Vs}'05"aWM3 ?=wŌ}:k;z^3m'h2-5:kyJ\ЯQ`۫ܕ&zO*J>2ٕ {V:/X4uE 좵ROyFvm{r.x}8򋡵eC37L[|͓ &4l>2ݏ.LY3yQG5 +6nC˲38uǵꭩ;׿<{<6 +LlXV*KS\ݨvsj?+Tg `r~}:tR۬OY5>ɨn a\VOܚIY=I ,`2ג?zJź1mzۃBf=S|ӪTofavU=b +ӣIx%ϰ[c +WjSu6=Zv<7KNܐ]VmĠ~)zf?kan⇗GNY(G&gn=Ƹu{M;\vp寓 7ez{ݝZ:ML917%Vݰ[BV9ڦ(5g}`a#O +^1kծ9}}sX- R>}VMYBٴlJ=VtWج] nNS>qCr nWsu)6k= +S;É\x\/KR?QԎRfoZ^:^Z-uS[oXwsײLuIlkuRMGϪ&oufW捩iu>ORſ[܋O6oT`βw^6[y}/[KH7 %JW;|5{I٩]ו*waW_'mg)C\sm7gK/JLw$C5=ʗՃ;{O]yMʹ7>^1~ez3k=&so/6.;73eu4k4Lrl~b}YǡVlgߪUҜzf݋RJzNP]hJ7?猚”^Gݓ푑]|, 妪'̵̛gnݜ>s +|7֨<,?wob]}&s-}?v.j:Ntu?C̲~K^ ,e5ݹKsTU)ea=~-/Eq?1xu}E&BSm7b{q˵nYԘw#޲7ޣl+&ԻMWJ5D$-qGB{\*ޮ朲gQ+XWzUkw,w\˾~}!+W]reٿݳuIW7ZvV=:=ܣ9qm茘kROM# i{5P {8d̟q7˵Iv'WTMܼ~z[J"ޜlGif&urUKi;J튬=4[63ڼ;aw-5UrN}M{~کr-еFO5Gv f_WN.2uip-5>fv8ګU^\yf?ҪtTW?IK%s7&̿8zn]v>=7[TZW>eCakL<;@Gt[" ˄㳘Z# :nf?kkW{7jT0WtAw˞uBO=ʸ*.CỎ^?' K*|p&Ԫ +3XLkۿO鸣Ѻx%fȑ.<*dWX3z _E?.(?qd_|b;_NP䗯mopI-ꗹ'TwG/ 딭?1~f=aļ+[:tT7RfdYiźԠ-Oi.'R6L{{CnHq1m<4udՙg<2P7˗`nk^n.ݸl⶯4:-=aZ#"3]~snӓ\pV-~Da٤C/},,YyD]o@2iɾ J\~:ioݲ ~SxsZ ?Kb}kM5K|5{SC9O%Gq?^7TsvM5z¾Z/ODv+YK#- \~Vi#\z,lwr7N/J:2c;Wゥ7-/y^&(V"k/ΰbr~WQaty +6)oORq[< =2h~:ǿJQ<5,˩!׋]\v7݉o~Q."5kv;eL!Z;Biۅ?%OK1*bcYW"VSxwcmRf;/E;xɯ1~K^Y~-&QVMpJCcә'>Ii. +t[)["ygT͙LDsSdҺW?ϓ{3E0\pau5é[5MG3h-Ig똹sS.n |n~WLJvqYsI`Z@gN/q ZSg,н߳jGGztpͶP|}|YaEglnSDܟ}U-nJbaO^(ݐTϵw3J7\F$'SiֻUz0K${՛9[ +L2>2t/Nc#7^Lky'}ثG:Kk ^6}%U^jM3l2ASx͢봧^eUVi5ݚhgג"]F~oZHҢ_:d^'{)Ŷr%Nm'ّ K>/~eIF!UMǖ23ha6~JEƙB'D۷[JG[I5VXtkΗyf4|%:Gl[~JfLXvS"a +wӶI1|| Sg|uTJuqF7.6Ysw!n()f8n.nd.My4݉?MD_gbzغ7.Ktׯ<TVK>نMr͞^c+K϶9/E޶Q}Y]'qjL\:_ݗKU(0\ \h7ҢL ' j4dOS|(xBn-{S[c ;tQ*>է/."}7G 1͋}k;P5ڥ/(jcY:#?9}Wd^KTooug~Wf"mnG2O0k֞{3/pEޞ̦_6ԟ6CڡJ Z%^'\ed=ޜϲ.cg= kebñiFw.H,\{wﵬnMw6p*Hi>% o<1Cn菗^κ-U,u +&|pnGN7=e)g}Qؾ;Uhe5=.֠eM3okq_xQ=nkU7o uXuA#_otwEYFW7{ɓXąe-ޓ*.ݡL:-ӱzGGI>(óV[&lFBoهM9ńnddv鍵r{t,-e l ?P!Ǭ<;R{VϽ(5N|3ON\$-7u~\1Uu$_X|`{!+]͗l1*DžO=3 e={r<˚W+ʿFݍ}6 +q4*ħX^)>- Ekĸ޲V]/m IWZQiS+`oxtaioXǜ'l]smt1.2ȑ21*:WsˊUJO8U<>YmqwJ_-^#M_̥+ڵ:['b扏,w^7ά­ՂT'G~|FOѷxM[gNþn0%*jӽ \\fs?>qYod8$h_C)R mu̹e|jKX}Ia©ӛX= z 6ݩrƏjfNޟ{寯cefHIz{4fy;^[={VVůrJGr]Zr[iEǚI+|+Q^f1O+|B9J/~}l2[ђӲ~0qɻ AOme׶{qg'٦@ng!L%]S U}* koiO{W;,p֎N:!}%km8HOgm;{,\qdOnJx-ܤwV˭QPvdr{jT5i>ո&HPE3ĝ+"v /Ro>8Xmۭ3Kw^x7uZ}'Ԕ`=;g2.|z4}k-^%k~LyƆ;ʯf +ntSϔT? ǚ >i2?{Ls%CnWz +xWiU=݂rgpZvgʧ֩+Ãd{ykr9j]])2alb/?6Gv7Ñ=?=N8h~HWЅmYO;>un^b򂣒5q?/aԬ&k,38ķO֟o6VsU[5nUoȔ1ֵ`//K?b7ą?=wvxߤ gZE{seȜb=+ؾIGu=nzMm%ת5Э/Qn~uY;$L'fGL6z9Cz"[xmf[~GyZnkm 9oU|O"N.Ljo\3u}%_KH6,4+}^*Oř˺,I6+lOG:pNDәÃs쳺l㜾/]>>u9 MElx^ǂns^y\U)tOCt6buȐ;ww&yO;/?VlY.yO 9wלw%;lOYmeZl2 %msmmwm󆝧:U{;嫈WgwpX?$yy7u< 뿙SuQpZ\ce;X:\/<2wϫ3o Maֽ26^U%3ޜ߼TA&M,h/nr﫮؃%b +9֖p7pV5YVF/,W:bդ晪Uul9kz;xs/0d~,[WrE''~4}WmzqT]]{k|r,o\tƾ7"4EIlV3%ՈI+/ȟ,.Wm~J#oϞ[decE[vVlrLUB["{ýIAWg,qpݮf'^o;Pڏl?WmH5m߱dORȋgm Hȩou25i ,or׮N r\7ld–N8Kb$OU|~U_gU?[f&۾[96;RzXЙ_,g͚C?o`G28:=X-vI{>pQܹfzWoXrx˧,& >"*Ce(7&uh j=6|5rvدV-)Ͷ~'*L|AVi|>|Ԟ.e[4BgV٪'7o)xj##|tXH [?@l-gӼ:]PUoXf}kRqr=aQ{ND:ӶۿG}tHvQ#oDd>{xҩ`OӼ'$RTdw6_L4}᯻oF;j~x{΋)SvqL7)T~3J3I%'%x٦MFӾpxΞa^?^n-ж'k|_w˵^YѾ'R5N͎3&> +? +s9<-=Tw] w{7Md'Î48%+Q~yٸ^g; +fP@h'm~B*&޹}7[lgܺqD.ݠ[gO8h-s/rɊO7Σ&^+y֩-UuyJs/l清[ɤYYK3 ~1rij>)Iyag.1fy_[}YU׿(caK1'"oȿ)֩j"~W̷gΜ]o 7C'Ӽc+<6q$bZln|j?ŷ++͟ϗܪu4T^Jmw)8MP +~eT_пUƑ6TӶ)WJ&:|ѹ.pd͍*cM=6٦Ǒ{DGaק}չ3{Egeg >.8.E& /8U~0={wu|![2I&ռ{?yd뀇eov%*IgŠҷ|\lk]Bvs|7\xٰ~kϗ̰K^;Q-mL~NKj [S+)}y("0qkv;_$z[vM\:"-PM{cTVegu/8_2s:k[Kv&В_c᷎xI-HfGoy<"ү&}-l7'VW=_iu|˖57dJس%uU9/:~NJɽ-&_*+~yZ7u [9*"BN60Cr|O(h.\*pͷ3Ѓl>,Xϥd}2QR~v_|ryy'*S\ֹGk{}/S/plP8e˵r|3&6~xIiFFէU3LHjgPcr +f:ODqbsZ Zg z^~d>p;QWneSKX￵o3Ԩ NTtu#׿L Z9a9iK<|ɕ\#]ŋӋsXgZh_ĥwgroghc$}1cϧI=T[!\׻㱫h{σ[/.2?&>âǞ˭Wt󬔼z˦"eEj69fI߅'e +U JO^<-F/*?ޫFGq+ї'\aX{05/kwgU8- D0>x[LٿgTb 5 SW<s^'N;j{~.d)?, }y Ůh,=)ݬu-T +<>^)~P{uqTsFw_m&vμxP̊5 ̘o+w`)K79K αz<#k?.z<9ضmOL`wzS5<` [>~{ևKVs&K6fEۗauE}oUtws̴qœʼ˞jn;_㹿g4o,y4{Fw\-gGJX6O>'ޡ /2.t`~͢S4O*09$5Jhtmn1w9빋nw=2 g9Dyb>_~'y$rk@#C#&+dEE:*Ew־,f!nfHrM/W]`T(=Ks&˸L:9A曛_,dqbߺn^\^Wd)f7~VVj|g.BoXnV{ŏfƒp՟5hx{Ѵ?S:]q5|񦹀i`vn*x\7*cj4pGdDx.\s+ !33Wtz8ԥ*4y/Osߌw>otE$eysOm{f9\29g?E+}aǾ>S]oY9L?/mszN7FWSϒMur>r½_cfkkLos;ܖ2αy?w{eǓ +kL~|~xz Y:-{3?%i`NϢeSئRQG2gw_lwO|+hx Ef CL]6Rs29km_f{$+G1ǾܼWj%?qg^ަssk}Um!EU=ˣT]~YCv-G\{UUi*Ù٭~Gt۾yw&R9a2]o}SȪvk/gX[ע//JzJ-4Zz*^M2]A{kW^րIm uP~Fm [M\^ZWݱ2U:1,mSm}(p9oTLWLw7"~s7V4Cc6J_'j{6ѬJMn:|sޤk' k|wts.-_6jJ|ub5:[~T`J[QZ'|{DSiSD?Nք3m8̒ڜԯݪ9o6 u&(W[.r:}(DʮGO7]gO7[ZaEO_lY s_0;U7J\6˛&}l.]o^&XP²Z9eYmV´{kY?`{}ʯMsnn fNnmvF24X̌iu_WѾ4uYL Wsvtoۿ A]RϮz +K}'@`ϾS?\#|Ҿ夯qA]"M'/=S'yo}/Y#s?y_XvɈ96:m=_XëܑJOo>ո1ՠ5Wf͚=QE0}zϟ7ys}[$r˅)}'hK~삵R."-@lЍ +ukXO۔s!7q캥-qޟ3Ns009 YO>C`GsD?TvsN*9Djwm9-2B]nbw@3;,62,+ZroOrz:'.4!Ri=-Sm +n?0Ӟ7Mc+sӬ|\ןYsɯ7g+,-bz<]ɞ$v"ph{ 'Wt1ĭxj׭u?<^xRDv=d~?ew2ϢM(=k~eZeM^Ȭ+[ ϥU-:qΥ[]mٌ 5O[^s% np'U[:qtwo{_x5/(~!*7VYsG9Se^}zYs9Zg+=52\IɛzSKUsב2Qe[+$~F6Xɟ;L1C/dI~3/4p|m.Fdȗ4ʞ޾GHi+.;܆e]6Iaw/FCrj̣YW#XfWHgƟI.66hPp}mfn+/rޛ Fr~m*e.~*汖ʩҗKD7YN:o'\-ZklBuÜ;=wlڲb3Q|"r7Aηo1=( ={]Yzǝ|3=2O"D5L;,99ciJƺ}sI44uN +zӴd7_ߞ,Ԩ{T]|7\9&_xA~Uyada|sr9]ŠcqUw 2}}sI]\ZO׍j"-:>jڄ(^;~gGU =|0iܮ4o/yp\as`/^fjog-k9$YjcY}Q)Dݦs]|[]&ζ".#[xYmAyaS枖qϿ&]ZUu0jZB%v^hwDBx\ +Ջ=?N^Jv}B/' Or:ݦwg{>[q'>r\_ Td]nRG9]Z/J|f߹v63vu[cox|^[*~x2e ;nWO5I^u/|;Q+'ӾO yWodJ޷-3[I]X$륶KlT/!x}k'4gizǸ޹g'pk&˛Rb̧$g?dkV%K0evE%NEO5Nb{԰_)LUc.I}{fr^z/MZ + +5ȟ[kMogm7_|t^pʫ&O ZG}NBS[呩7jgl,KT-[*>KOtEcңEbsbzߧA VgK9.1N9L󖄳6OWD8f==4BIX~PVw5k5E'OolQQ0!u5[hS9{^Z>Q޳?"&[0cIҘJ{r>߷4{GfE}Z<ۓ+뵫K}p'{LřѩWl}y꧿*hϫlυL9 +֜9rۇaT&T%柳]a޵fk&_"ʤ;K҇r?{6 t.Iڠ!ߥ#}S#dmFkH"RQW߽(Ib{ɨF{gQu -{`,S>C\j 皱ӲS-NoixD漌wo`}KM.g~Ju96Qg^sע]㱲|qY"M%Sٟmh4i9.Sl! 37I>i}éA!Gvt.\-1Ki9o+79|jPNƩ)ˣx՝E1_IwuKz*3xߜ"%^ܯ{A˩ϸe})T1U-_bbje-Ŧtu -\Y!Bm]NM=YA3ub.Ջ+V9㴏gCףk~fUqTAc+Nƍ\ZX2KN;ޣ8EɮL\<~ݱ̣fd:Rj˺Plu6w=SrYٻ3w/p oë#G.7ϼ-u4IYFVOI޸Ķ16k\}@,us657b Nykd{ I=L +fϫష?k<=fVd|äBYsdV-^'8{~WG){ Ajd(5 -aɒ^RQS;ʶ^S/BTd?{ʹѩׅm~aṼԝSN.0zsyjb-ڐ䳡Oʢ*sg?)O񳸍jruHNN#HX 6snoq^Q/lqjݑ.jxNVrs< !W2W*ij# Cتs{ggɐ +}7j#oX`x1IdTJjCT Rr9Ol6z٧Kjƻn5[}x9r0)PjMC-<*I?@}/!:74-9Vqrq)UW*<_$: Sg.O uSrM'w}vO[q2piEXߟ;^Ę&LYN齪=9xKŞsZ't=~]GBL7 nXIWOw[][sV9ΝVr8}bʻ.7ݟYcj'͢eYn_w_ُs"jIWzMޡװ owpd7oWIJT,HTb-Tpu~%^ݘjذwrIsh\zȫ)Y,l_wGѧ, +6ЁGwy[gzĸyݶPCgrE*s[=قvK,Ε9ۃJG.q>qӲR7o̸_$LMq %=gwfgqef/h>Qя'Rc^.~o炙x~oX⫷;fikd&_'[k/3U;\4dJCqKV\Ah%gY{b#TGw]iy-NBSvW޴? }ʳڶ.lұ"+jO?k_s97lN!%u//`x=K\eJWh>߰or s#&~ T8C|3V+bz2Y'5u_CgwS \E +[>8Ч۴jvUlF9b[isW86O^O5(~zpFq kUlKWO^vgRv^ѽ8oK-; Mlo;|ڿOq?ѽ5k^e-[+yn/?kܫ7D\ȺW:ɰg˹geũhrrо ym-7ΐHʳKƦA%^ mߟeieqMbF59n]8uںǂd~|xpHMtKN+NO&g.|~{y6Dʤ})?_+%<7yլ;sý^*}eөǗ^r$gʸ:H%f .ImN)n ;m=nWNw)*խ? u7baٶ).BL?ggb`4)~u;$%J7nJ\Pc$~*\ڭ"|~/HﴫoDLgbee(\k/1Kն%{'h3ę\bw^[uxOA aV&q}gz7>=iT1I{򜳏̵ڽGE7Tvʻ'LJ됫 +9є=}Nwi@nk5NO`niwΜxto}ݫ-qK~٭ce(GFk¿{"/;fMޭ}8׸.%϶Y&'j{IƄ;f𭡑I[-\7?iLNyʓU^[Ϲ".R]\wkzꝶW/I3{6+9ؿ$*k/[珷+߿@nn0{W#3Ckatgjeuw"&exиVE3SX5̜\;'o;_5^Km*7W}Ͽ~ ݾ/skΧ+R;wjF:N_(mgd5k#gYJ9f+޺NiSѐ|&{Z H\:1gt{'s'48c$+>3&zZ=<d{IBJZẘ]x o[*l n _(͵vO]dp׬iwƕ-sE^KNVeyPv)MfF҆Y;;Ymi䵒EAr-ѓQuf*.+ |;ӱ}^ +&)=V;Gju7H1;kwGkn10<ryY[9sr[$[v}WRC5nl|5]e3g-3M{O32h1~pI[Hߪ}{`mcɶJDUDs-RVGOܰn3 v9߯$}y~M<=QZ熌]+b[;˛z#G?Xq7wugN9q?EaہRu)MŰ6wNN׾KgC2vZo \m3R,V6V18^|6gW֩(_=;k޿*"ξ٠~ˆ!Rʌ273$*Ȫ-`碓6> /GjEU<3Bn1yk8ZȚz[(|!#{ kf>,aЬ?Y'V{?pnve{b}_ ەvXT^')g[p`wE\n3=շ.\ctW&HNܧ|syG|7]_){ev̯4Y;%w;ȜczU&7Zdlic6~Xֿ0DA~{MN]bbUdzko7_?ܴcojå8϶̸aqO|%_=5>>ʿbԝ%Β952D\ }ywkn/=VIj٫S?iMovd|9rk4W:\Sy};K+s粅jto3k&۽ U)Vr9P0?/~VbHwG^=TktYԪ.fO:k7tR%mU +lmԄXzL9ɭ'xq{%MƢY/s=^Tͬ~g.)8jU-]!#n)W{dAl̝f;aZLI Lb|aK_4{83كw~e1/޶7j [U-OǬXaWp ߵɚpCǗmx t3iT+bt{vJ[*♯6KAv0xSq{iYՉLZ]r>%]kRvc%¯`=hn`OX'9=~f)k(e_c+/Q|{kQС_1^j6(7=dv݇[6/qt'kB}ټX(:/,Y~|+5X=OkIyuU}˭u󸅞N/xoNWzJvNmCK'QV5 SZ"3ZdW歟vIWs>=_pX_&&x^)N3ts ) F"&Ky$~h5/Λ kw9m-6o<]l^W>Ⱥ*7%M%θP =_[^Z2U'v3?zE]ώ:`Ƨjow^5;X?K'ȷ)+o*sR a,L;^y7K6vfnyi5ߘ_,$yt(yIx5=}./{v5yΣ{Ms9VߟpBd-)GΘdKf9O4۷VM;GMWfP^|tn?QT=0{LF k df<_,~XMIKwekܞU=9b[䴛 472i^SEIг>kd~0l|<߂M, 9[n,]g!&r}BEQ=]l S]n{v}q9l,xK=U^N +rCJST31NS iYG3ז{ok䳪5Yv4~Ko[O=^]-dm* Oϳw<%d0 rlɿ<~01oOՆՎn3hѯl͸?AĝUV|fV͙dt^f2jwǰ-=;vsW=gxEƿ#v0pAe˃׋3Ċy]lSNUӷaV۾c?.i}IQ_7^a}9޻h&3nv (_nK/xS +7g+3.Zq<8gi93 +ftY&7虸 RIon1@g[|{Ձ<;]ֵ[+M&eqB|ҽ]B5oj/G*?x:nۃ' +boNHٹ7` ϔ4 SmzcG.6p .k5/]Tvzkݗ:˾26&kks@mQfK؋MR&\,P/{ǩC嘷| kmyuyϫKqm'Zͯq|iΰIc-6OܪCξRhZQشf|Cu/_| +H7ؚzI-[V+XXV={Ot:dL{;WZ+NgyViڛMG]hYS2/V>ʕkN9ݔs.O؋1"7/2[Josb}s'_loPW7s<-ϹQw2"FϬ{ fx%AJW$׽*\N#?cۑl?Bx)(yNvGZF|xzݟa#_4벖}OsƋhi%)=7_v|ѻ wl94î儼IuOvԸwER9f_hZ:>;Ǭ76=9kY@k0b[ -ZcgR0yfvIqɼaFN><Ͱg^*SgT# %*'-4S{ ;N]ƥo<=zi6s}B؎3=<~y  +X}b;VES{^ȯ +-dȸqg̽s)la}{onh'k|D?_ftOһoewϚn~U53 +kU)͟/`~;Jƒʊ],by,yK(7L 핧e}PA ;,랽+-}Zin$Wf  r.ۨW``01To.'gsY#dG)׏ֽյ)NϬv//^cӜ/lTtخGHi>d"S]gޘl[_wp=x`e뿎Vzo{)`PT@pugމyRUǺmwbD}ғG/WJޕ[V͸vmU~;üËt/ΗpWyaPyu=oz62.ix:믆͓-ܪHh:ik>%)}X[ݴG}M'w0NTQ'dm~R[|JkmOO.-ZtϺ+f{/3yW z_ȱ,4׾WߧlJr^lz@bT>7/p'wZw"Ջ^JԁAFsդB$԰O,w퍟zL2fߦ2i*|a WiI$ZOm)^LNKg +t As\:e3uѵ{K}bԛ7>wv+(j]@[tvj'u(_ax,ϢsT/H˾{}ҟc!A{O(zy={fYjO 7/,c +ݳZ]]vmyߣ ?^_umo;ٿ< %ty)M|x"#K׊k60oq:4̖.3yeFZC҃oz$Cn$=`0&2[JT5DKdؙ3zwi/m{wތrn+Tn[|dgx9snZwt/'6TinVq؎=V-;0~&+b!ڵѠY>\"a~H)ce'_  *iC^n4eccw2b?̭/>c~.oy=X2DޓE%SqG}ثFg*NvnM`)qjCSvʻ.ؐ/. B7~ϗ5>>=cUlV\aѿKd16z:lޯ V*rWY+NX丱ITWjOJ.6h߿_W=r_Zxc&C7d֋Z>^k+'PtǍfߺEٜGH):Ty$yެ9ykwDۊ-ШIսݬG>&$ ڲbKS)MLStbz75OM +tb܃SoZM;g/Uk~%sEK؝9N(tJ{Q9[xzsғ>KNo-W+3ѠqЁ9^<@oǣ'i,cZ8_g[LTK=83֚H}d,z!mI)5pǯAEܓ'.ȺVwt6.ؕ7ͼAf̎9;v;h̻msMwqdeO}70i͊QuXzdNVk+}DaU>hY\oQ mco :>!7fl}ǎ'jx +ݰpwֽB DnN]w ,7^RE2Hm'V}ධ[.tezI\S )#Uh}uŽ' lޅ[kDv\/yzIj"LǭĴsL;uFǾ^-N~:ۨY⛪2;sJa\'XB,l7nUOvSSǧjuoUM%T9𽹬() f4c{;1o#U[5'=6ldrW&lsYouuaS禭y皨hXf6oQrzEflJ|҇٪VK.oVYHǫ{}}.׼P;e|w{v >}SQ}?bỰ\~7T2W0q8[y&SϦ߾Y\?,(i W؇}i *ٳ͂[;~QxesTesl~fkӎC".n]9- r_E_-+/1Xۙh}t]Lӱ"p Z>x۪{ŧmmۯ_ecm 3EN'>]Ǒƺ쀾S2: _] %׷;篜*d}qiҩ浪_&\AP߅MUGT%ޜn{8k,a\B+_P^_[;?z?̨ ?%5r:2ݽXTc"tmOVb"dtGu_/N;ez-mr,~ʓVy7c>u1@ᑉ2g[hZAnYݓff>ʚg .rh1tݯ)u作֟wm~l.5+æۭS.{藽 'n.=ym|&9?x6S䊻ShzkgBvq7-V1}aVB4&eC1s۶r$7웞;˃f/dmw/p8aٴ"u[710r\~c75E g7UH~>yan}9Ϭ7&|Z|}CmSuxI<$EGZ56hMNzߟrz|TA#ʶY{Ų/B5-L7GAf&6j+jʔ?rêb]~SҾs~ܹӲ%ϓg̮Χツ£g rڸȿ} ǎDM>V`wvmISM_:shFGYxEk%A5号z^M?w_5ٺ=hM2Zx{lWEnc!]4[ZjEM";R-/_,L׷_hYxrrk뗅7oYR +Z3sn'o7ԵjcsgrL,F/[UZYۿ韼װ˴q:A܆~m?#swի~!ybس|+e ;#_= E>vCHHIVOx١)nm4.mhnюjɮ.9`6Ɍ.3׿]LI]1O߈Nlaϴ jwZ6+vHbSKO:f]?!CAO.saу,*oXi0Q[`𧛽: 9FeJRK'^[v^Y/>bjgb_a`ںmݕ+8 ,U?,_)Gݎ/ ]nrW6YsmY›}SxsJ*vo\Ʈbrһ/JJ]]Kp +W{*}'7U2r6uG9D'LSUAgmVI᧔e)!6~~vR{ڕ{[n~I{h sq_ +mɾ +897efL׵*_ {u3%K Y5j9{hZޝ9CU`KjlK&[-B~2\c(cCELO$=\rig~8s޴Ei+&9mђ[r&^kRlNEX6[WRKKf^cas${]}y{vށ=|uN5'E{6}tGo٣)v OZgbHFu38kɶ=>>cU/|%ll6w=ES_-6&?.o^1ǧ+yܣ,m3z퍓߲oN*yΛk.>/r). Zϭz2K\9ZgO'<ưy֙yzg8e;MgfAWpsy.L[E>])q޴5ys7N?qao`ķ +e*:.(4ds"㍒6.&dUCf+Gn3Z>eǙD?i~Մ|[m~3LfWBKŖ +SlazM|W/ȉM_NBg^l~tZ yϔ98v\R{LeikއnӻxΫ]+C-i_y!)wY^=njWh“97%<8#ՒOO2jxrR#2b̘k;C橧iMq\k [tm ۙu&^/W~9bPdP +>9_Xz2bsJ8JT5_ut^Sjb$`组 k"oVZBgŔe $>(t'[ɉK?488qQ!.wlXt,kV]$?oXn'uقN;..ؾimݸn 7I^[o/v<w9K|SVR 򕦸4)#z_eo5T 45c~l^߽p{7|=r`vx?0!~WP/xYŭ7ٯүUp +[΄~gX|N?"~T(}z;Wy_7[*f{*dК:DOUڊe欱<=uub˽N$VͲv zt&g}4OKM֪I2ݻ>ۗz%uK լoNR+ͅ_<#w "_ozSqơ}M.a[zMcދ_Q!1ZzW&"P<˝6kM?Ys} +O=ɰ*{6}f07R"o$݌s<=x篛זL_3'|P?v7p]W.?LIC4,teb^2f|Ye U2y޾c^UKz5&zwrʓ>f]&(mP;#Wq|]tvه>${R*~W/K2;;;Pl:uCF1^wMyIaѕ>w衸sHn%'^yngIB%Y?ܲ Q5'gt~éRM ^T)a1Z2qhǺbE%e"T{mC埿ko~8tMS72f61p)nDh8#orG,ٸY^8}_$_|]W*)yWW ,z`}5يϘ̩LĽ)|'^Bhʮr'pRV=|ܧqaי{ݴZtwq]W\]g_(NY~5j O}\*zsKYTww ϖYïΖ[ߖv>U52HL doWܙUp1/.X*.Lx-Xܙ{uigA-Jokl>޻qlӲޯ_-rr@l}9o>tA#|"F89*qJkh.r8=9SdWQ\ャRYkKzZ৹n1۵SX֚<\db5:>NNGk.ẬmV7E.n, ԛQsOIh~W!ȿT1;o̟R:87k)huS4 jYrvݝe6i)Z*mlvw~FYʼnO.q +w>zù{^-t1'gqx文iboTxpU;ws4}eP 3}u#O&높.^(/pwzM[;}}V,Rev z\ϴPtJ3OlL(:\0MlW?mI)S/cШYga)bW\̻ҵӮ_6yD;+۪zTjlzhKR>t{Lj')m*?zI6f텚vʊ wOÛB#fdKJ,+hwYs+P%$bP|Z?./yjH)% ug;ؽua6aמr>-yǖ-5D=稴ƂOz},l=[R +O?K6ҕ<)%.Ǥn>v}K8S'u^ =?Yj]%hZ|~D̽9|b%| G/ IVj{hxY ɶn?:X)fO]]2}Ě+uzS_] z)ʦY2<͇V/=jwMR?_, iNnԼ8o5I{kh:U%2OIi~o>M7]~+FUu?172ob!$U̔܊?c=ƞGo2:jx}Ig7K}Pqγ-m~6:u˿gB]wOSf{i4?/[}(>~|df+Iɓw!y\ o7J}_kU /;}>yWwJqNMag؛tϽWY }O;Syi`%mx>?ckk͸|"|;! KnݟqUqw +~}#Es٦&?_e6 XwB zgzqOPQt۷ks},Ȉtp=2?ϣ7OUI=Uĉ+_:|Ʀ_&4\\u}u_T=۰5{ǩ4tWK~,_bz~WN YjWy?q|g46]Z4V֓}NR6I.vU*ʴ5Fˎn;vڙU{"1o n?U"vLqxWt`Q˅록 [g0̕f{W2T*wfl-i*ޮhP/WZSlvSrVla4aҽn9k.~#;OORn_**4/(mҷM}Wp͛|?ҟ +ԧz;ݧ]t&@Qv-]e^uͯyk|>H\tÒsp,a-Ү͗7d;gwK'i9;tƧ8qI\Z~J켶j$ͮ:[MfM(-!Xpe+Sך}-+1/EۥGgݹWvdυ ?Iޚ{1!!|c_Js[t\k E[52 >ն}whմk]jJƧfeUg&ey-сg^ =|oVg^ ݼ1qWڹgYҽ̦bSY)[{ҽ~M|d`.Mϖ%}PJucsWoɘbQ-: &Zw٣V׊(|g;Gr sbxܔq*m{ώ{ߜKo9Zwq;ӷOP\xiFX{iJ\ɨVb Ѵ̴'FrAVs _9`Yb[fifx~ۼK eΝa}]XÏ-;Z[nzf$IzɅIZR2| 'THha>,/ dyLd+xy7 ۾$ܟ~7Y<ާ5^La#ĮӫZR.V?((չyh^qo+>|W_XvtWS]ʜ[J=P+6.wW8ɹl9wk.]jCcWV&o[l 4WOw-͒jUjTq턾;y/Y<Ӓ,DZ#Ín]zoex>oy~>>q>=0ǹk;l[w֪$o;-ΐ~8cAJZ'ƇMdMpj=ٵ ]>~wcjٽAq" 1O~jeC3w9^oc纷"JF>mj=қd:糙9g; s-BcN+}3vfŪYnl3-Vp2VK]ۦU}xŇ+Yru28ki +Dž1|ؼ$>4,5s:`~G\YǿEfH?oіR"[ϸey&\]Q!l~L&9sq_vS]Yl2?UyǏ5ZyX2R??N}D@^wG 9swUEweG;c\kKbtbI`F^ywEhy*U'x_iU_(\0XW4iʮ*|௓ͥquΙw?:}/ Ռ+ΟCiFJYW޶oe봃 +fX>\;,4M]6qǛyb&֩ƲnB~noKȟkt.֩ gޮy?LB¾Wwƕ晆ppzq);֑K~;o˵3._aÓWpo?*~2ۓý=h^t'i٢ %.P_z^G,STb-;bcj.%.}fjwGH0{{w2[iձNou07R\זY욓jS;ok "ffi=~:e7 +y+)׎F46zsިM|6.[ƲA9_z{ gu뮝Wktw-OǸw;0V[jYͧ̿$O&ȕQt-mr6jlo?1^մJOvlt+[cyl%Mi?Eɳ]V|k%`z%kߥn7cջTŀW'2$W5駥7L :uwngc3M\V^ux)fPozr]k~&: #'Rb5^9>K5߼o鳻zh틺٤|CgvT]{P7__|ⴥjLĶXk4VS&>>.kYVWsqΧLxH;0ɖGkl`JXxE & ߞvQٳr?e2U4-u{p÷LYc=cP@xuGKDm?4׶8Fd +tk{(_0?~O]+Q]]y}]֯7z͙j9kyWf,;W yXdC%/ZEUw:q|wmiٷ ^&MKy׺>*;>F͢=ۙ[dA|M!c &o?ϫ5aq3*/y_\g$|U.+wB.{:$ڸʐ )gΗy)G ˙^x>Mbw2='\$3r +G>ӪªeCEIqsYU> ;\0Kί7]\/G_8/2.Ohm{g{Ty:yoRuXmԓtD]im? ֽdA 7OwA,OCOM/ ~6J^#e$tT\آ>]`  lVڕJY~闑kϻx&5F~ñ̺m'k wki؝Ү%Hs#ySuƼE|+U7af% nĦ}fO}|o_76(u\yyגՓ޲*74Iҥ%Q3qqU1%RN|QSpy)i)MOW[}TUU~?5l妖.n$CߕV~3y + +/#NYh,^##[w7AF/]do +h='~S 3X" ?ܛy@ă5o`ZLoĿO)`Qd'k즚7p?۶rU_P?ܐO2_o^>gUAń=a]P³\Nb/>y栫ʲ=g{^j~MdKX" WHeuiW++~(.@K/sUc;.Q鍏/isb2v9$1Bq@yˉ;N"vNfW/2v7eZuwe&9< _̶w]*އo)~=.۸Z{V?^jyC11MrmaSSX]{h%3h]5s9JճxDzxY?v~m[,"%%s'Ҫ=}6FQOs-ְzO:sΌXUe:SOQmeVy̭gF=zMš-5L߾_R7&(b/rb{aLͫ:R;Y=Y{z:7n +\ *]v}'6iV%;d@tuAhzIK6T$s?ĢscO\`u,RNO^Z-ڂ䟉O_9yUQK=7PfH*f Q^Rb+H~|QGe3ܟ[Ƅ72س16ei.0|hpeRZEo7]$^gLLVrO1h:wM&˼MnY|/+ϚmL6[WL+[n__DξAsEKW"^3ˬ~ea~- +:w7ql/}')NΔԭ~wNHf[2ۅW6EG:N?ycr厹\7uJxß# _m.rV> n_!R{b5Nhy`{~Kw:qm1urvL>$Ϙ0{?OEU?˽^`ٺoGW8׋_asKAI37=W i ]ȞݯNf,1j~MWR``/ǰa n'.g}zmzb%D/yE~՟ڻd+xnl]|Jn}v :HOz7AW1.N{* ZNvupʺhՆTfʅK+ݵln`w-ٯΔ.5.pUw=O𽶵ԶZMy[}ckYևnJu76P~wLW>qަ-vK[g˖^Pq;}Swf9 [k8!I[e'{*۪LD+v]XS遢Un[kvp㚸oLWIؙ_~S=­Ņ,dej“ +;yޅqYի>]+9q>;YZ>-Zv.Oi=|kmƣEnN?GDQ\f?:fwZa{ӿٓ\tTwovytC")\?[תVOzr._KWvV<9ĸAi߲לܕ"k叽ܮog񯟧73 |gvøKﹾ.}Xlgmb&q-eL,ǝ3e3f58nI$Yu?)8p5CE3rSn$Lb._xtĒyZl ղ8ps fd/٩b{#$͛[j[~`zئsќ㷿6 F}e'zvڿ jlxcc 'q__ʟX.׾&PMf=Klt=)Ӟ~5ybZNo\u]T=&t4k&=ĆLսZ?2+giy:|.ONR9b3o=rYɋJю=k]sKi6-YON?N[c^r=cέ #_\ťz>Ǯ4f[m͝'.;vn5_c_|4/ϞzZ}RH7T޷Sj~ٖ@m.4vwe]Ջ۟j-f.?,tS~K6;Hz҅M&FaT|mq.{̜v%;yNUWUL=;)WC /l^?>rD*volm%2>W5K~:pcj~X|g.g|jʣK3%^}m~Q#f%Y,/g?is߹[&rH[~|rM8gvpAcu.]vI^ +L>niFx{)d)UrV={L*&jfE>m"5]u+Oi~|s'xlqz6Yy fZ1c/,YQֲ..ώ/X6j0?O4jp̍' =lQ;8ùƧ ڞ+1#zfgt\S9쮋9Qq@iv5&w+rxKl՟n;s~.sZEfhCkOu4Hkx.wFfu^A:S~)]rԵLyIBO184,$E%EF%m+K8LYP_9Wq떩S>sn/Z \+S OXNs۳M<f|?-my\ͷ[&N%=;}}ȍgD ?i=e.Zm應kՃjjԌ2VE +?vj:aڼ+W.+J^p +׭;uE̕ݬ~g=\7p?|2un;rm5>tlW0:5`X >S6Zn+ϺN˿;N9#QRAyaӤkOI5euMT}Om[nr =vͼ2UBŏon**]f#Dn2s=}pKe:kt{nUL +oWݢhD{s_ZCnncC3cs!q&|#ʖ&MzޓMSVl=85kğch<5,Qy9+$Ĭ45{d(W\F۾36\vtE1ӆ ^/uE:nSvZJjCۊGg7ݾw~[̋'93\kg-o4(,ZwKϟhsRC_Lh //w +7+?pls:''nX8>=ϝ2M_߽\7?̐U>7_ 2tߴEϱ<9*k/ϭv{rS':)ZbښƠuN9ߊއnoU9x-C2G:S$g7-WEReVPY{{-ky~*ή~U?(d_R~?^|x炒vb<=$}7;|v?^AGܾ Lue핵At,ӹz~K*d[vxt;BYf-zykKjj?+.eKvjYӡ6ȭec]Yu<tEL +/ݷg[Wu.7/}7y]X:6=i}0s`s/X.8[rvGfTZO|;k S7sK sJ;<;w0khY=-i;*k7]/.gw.q񱓇բjt.wG)M¯=6׸KAZMP gvqAƶ ;fv/}VC=AsW5E/*g{ Y1F_'66mrZ[ŶmmǏCLuY R;C"?o{WO~4yzS.&vtЪݯfRy +즂?]o?V|>ne ;d=_CYDH5KK/Vw,/gX_QPȤدk[ }O|}~|~ϛ,~Uu2U^O]Jjis/qkYx{A[Z2JX޶M/~47OGq̈sWV4b>hrly'tOLir&w]+NsQmΒO- UUg[@\YS>Y1:ȶ՛o,RYԋq*&R:+9;=_V7FZf>}‹Ԡt 9t.OqӰgy?ۧvs^rOlvO{9٧0AĤ 3 +4?hg1Ns_[_!oT`BƫZ8_5-V*VzF;/5=xVGi7izT㭽BN?λ'~s{1]y!cӡf +^-MU*6:]tمwͅ]sYyXE8 K[l-^84m-YĵΕm͛ +%2?طYD1H}sHCu~M֩9sY;?llYlUujfivmķKtX'm^ҜV +cYʚ^reoI&b~uO=QE&'4R;>Mߩ/r ;˦eqr-m)3?780zNE Gg`iZ!t.@n%h=(k{} pGk%^:䞺6Ivw>V=ꊇys:R%;G5;>>LI9[EO'x= ,'bn/RIs)goZ8x,n]b-zGwNwm?F?Q?ûܽ f% >pk_&kL~^+_ɿ`Zj4] Ou5Z$<3Y2鍤s-m ^:\`Ubں(ҁi`QO?}Ws|㫧tֻ``E!Ű΅}\c/>`³W`񩵳D{T|s%_Ml>[[,;]kȼUfyjl|u՟i>OTv9q~ wowPWJθl벲ﲐ9cblʟ\ +TN\{5A{O=[M?U% 7'7rm8Kژ:5 +3ʟ?|i:?!`6>M8>o_Qe0u?e\V?O1e)߿6$1vzY08* [R+uH_`>ΓgX-;rgٻ-0O\ YuwmQrg>y_5wm{<=.ohi-n[~b6'O$̼xNv +bnOxH'˕ܕJϢgZ-c]v{}3)W-6 /m7;wI^',y6Cϙ<6^Zilɣ7xkpݹw\S{m]<?l՗7S~nxZ\^9/a#,#wmҧ3=_K?#{n[ڬ$8u'7Yli~ɪ[Bym:nZՑSulR.?yy?,d5oqhW:ų;w<Ӝ2+N̸I*Ͽ;/~,#ELuV}&%";ƅWq˒.M,Л__2-<,qssmuEMۋy59;9$oÜ{٦&wZPj4kw7 E]=TojWߚ_άP5~r6õ׼uqLJ bWX]d{Wׅ]&Y9iھ+_ +b)w {,)Jٳ\=pO^mDžӤmsz=Ԛ !#\SwʹkWٯb5YHRU?dƩγ>9ݺde?ʿ*,Ydl.pʐto׬ GtT=JYsr]mRTS8SwbԻ?CUW>w6|Q/~YWMf8_sQ ?񋉡̥ӛgloƕ}<Zح6hX5׆+մ_?UYojEhh%1K2;/]kYh~8SxPң;]?b)ndOC:;/4_:DŽ 쯜`^ܳ fOG9d"%^׎Οٟ-X|uI9 '['3Gʺ:f0ГI_뷇wN︡SLpck40sxq>XO_kB6xطeKO%j[wu/>C3=8a|ߌ/)W8yNX/mwQGY3 +.1jRe7-)^m̵,{{*ә0Ӕ} {^s.wϙ?gI.V#Y1u=/̌X + _906+K٩ί_{L\%$,`Ehf&]J͗Oa ]}_xFU%rnխAoBguNl8mii5znJq݆[ +EyRW~TU3# ~Cf.{;^DE=UNw5me{e}1 ӛ0K =KbS;KnL(|ǔ·8j`c;]⮏-2%llתL Nx;359?Y=\O B[XJ_ju4{2bF_ɖr?61wEiſHSw|w,KZ*iJG?2ShV|˟ 0-8{Q@἖!iI <_{J̧DpdWپe&=po͍mѧzSٗm'l6['Yɤ/xYp +.o|/SSl7up])οne[,XnE $n\n?wN%㜅'3Eob*"Z?3/mi^sN',ziQD/L=ˢoz$gxOK + Ό*=}Bqc=}GE\>Np!>NuA1%}4SmIޏ;'8|Uے/:&=otP,0hZw֙YkT1I ~?M+uMIR3~J 8"Eok븴<:|4s3G);-/ٱJFSc" ;Z{'NCf)|߯_S?yɧU_Vdݧf^U즧s3,u_1[جVEpixB*=l4YBYڊC˯u^Kr~bJ?3un^-ȝCZc?j/I]4;?unj[_yETʿ-ڔ,׮j|`1umq~ MSF׸~=ӡ"VgQsUlB F<7!ȚN0Z@fε_$O*Uݸ7c-j\nb^dB[#x{qdYZw8]m?rx2$Ǒ/w*:-9SBBWH>s9*f& pSť;S.~|iOޗꊦ0W,iQd[ aߥ2/?':?ڥ ²}dO/zfbg^SO3 8FNW|6:g>%&?'OjL}an g3HstӶ$:msh~+W%eJۭsr\{7Χ|IR{~ zf!&BcORiX{f RY! [<]E"J6}Nާ0rˮ oniֶֻh&溲r)mx]:cU?mk37,+q9'䈜vCǯ:^ۼE>k'L;@2T{/vyxi)W%ݒڠ*uq1e]ּ {^W?0Z|23߇++sj\*fPR52.AhRol挕3O0ˬ?M/_\mᩲsՌOJ.Iv _vy>A2XY1Ej'F]{XAS^Qoa}?ߜ+r00u=Oe2˖^9ޚD"G/mox׳>C{{9[Ƒ;x+*Iڽ^k+xgA$ωS>]ts>/WfNm23p[vO.ӭ_lSoׁ|>l3VjY&ygo~r?( of {eV 96w1P>䐌UXoLZҸ{Qu˙\iAF_B*f#pc/P횲ˬΚGB5HleW=gz?8횢[/^=_=Bz1)v8*0J=*yWȪi7\1{k<~.QJN_j~mќ/IMhs^N󾿒\=b߻߹gRyi96.`-g'B_1l:aw}c?sRZb\9Oߵb÷_Xu&\zgW_k!h=l: 2< \!Qӵwry_6юI7ȬhN3k+\^DP75w5{|&<3py9GD櫅КJ ߹^k3٪s3N4T(jslrM~ÿ6ץTE6yX&c`ߕ%wRP3"n?%=q2ݧo1/bMHym{>K-A!ۭNn-tP[cnyax2inq"-3Q14|OYko8bYNc|gM[uhgJiN6p?5m^:._y}ſ.=N'sO휌xk[DJ&NQ%o,[?g,95R~K\\&;[:&A6bF}-LJ͓:ת3k󝦹j]oy-Wx1@>53F3Y6OS&̨Y$JFUqmӲJU< +Jj{5g[k2'vŜz_ԋ]H;^/E!NfeZWfgK*m/'c1AJnYNɐƸ]1y3M-]╊nݭ<}bCJֿ~{#fظ{Za'.sή? l >)Fm{z|>fbDX^\wLò}4&]jzqnɔ-,Qc[t,5JO*{^VK |kPy6S@-Da]RG_(0Y^FgRCk֓y/54>1ڽ>-1KJgL9odb+3x|):nZFolju*E6~?Mv=/0Tx#9i;2'`·~>>oEӆY[ի3YMqގ+&OuX|@"M}>yYW7vfݬYU*xY›l.Z-_SڦJMt9v؏ttmi 7;o1=c)%MBsZi~Y9:I; +_˾;x3 _-g{d>K2S<Ⱥ[Uk&3ٟ6/Fk&^D/2i_S[׶=bVG{MYuS?Q?W{ޗe9L=scȦ_'{iH|;#tf\!zϫ];w/7}fcB;w2I_*x-e %Va⺼lO>Ҹ̷nZ}rU_(>fny|*-5^l~9&zQʡǓJϯYp5k쿵luΎ_<曼 ju4)oVn%LQGOv]esuܷsb:]].sJs8޿-W8}S6^hx{IZVzhΖt=ZIۚV'`wjb *?ϊqŠ^[o[z\\6z*TQa-DFiȚdm4iIbޟK}r`&Ƥ%8_ƽm*6; :Ա{v0=~Q{U/-:'zy:7K3-T}Em)^*TlC]Klyƺܪ{.fY5X袹1+#56oc+?x#~:,})𬂕q^%+/ܕ¨/j }O+qM>ĨX`C#:IJ sg|qIjBFo}ojG Z1%eK KwzeX?ݿ|z.U}f=UmyIENLw| T<>앱`}\jnYݲV?nB-Ns|ɫ9i?abҭij!F}Bmɤmxm0#t3{n3>&&F,޽/~_cy%ނnwp#u] ƙ[Q=TSEVh(i^+V.b6U/+xϧ:v4W'Ϥ t㽞>M +g up?EdaChײz_ I;ZϷ{kvU^ d݌x9ck2^޶sKw}ɚ0c9%>go|ř[YX͉/,b7M)x)deW=n[aП̱mQܩiNʎw۰iYc\1~6|r/"Գ+ܼzgN3ݧP`vkJq EwO^ <Ċ/SX} MS TFNIw}Lܰ+R[BZq7pd>`a)-tÇ,Q[Z{2x3w9]ңrݺ0ww'45=X.zzF] V8d_=sW{*y>w[wMAyWsy՚+o1i<;ޮHگxc?2&n?ROxVA-K:7}bkN#޶绝d:U -$2TjdSOI?~i*79.[we~WqGADքkƮɚc^l~"%_v/9>AáF%q̧t\;}[TiK,ū{X +NMi%[y}scBopP_bFjUgnvs?"@%j~gڋ^lu\E/>ex 9Rцgt1*aҨidڪsg<}ƯI욨\k/[_t& sN`Q}ⵇj}[(DTnYzHޭºE~6Vwk_n9} =+132wrpMVi.+=Ik)?Yh0'# ol.7<Up2#Fw|nϴEֳ*>!HzKTjydJ:kkٗ_$V;3HRai[cB%ֿUfe7xIii7%K~/萻\E2ecGw; p,yRT뮥'4`QCkSWK>ZlqV2 ӂ|ޫ=-vWp:+??G;?;LN|39˯Z) ̧<0ߝc}ggSY>|MkMBE,v=Z1|D _s#|¤[,-eK*{5v 5҂= )!JˋҦ;^eƛ{~QSOXѦ[$o, w?S]>)H*c.3ߧYIMe?8Si|wEY}> |3zTw?vΟpҺˤEĭԓ\M{o^X0:ӊ 7%r^̬nՄc7,9U~.S Y4yǧ_t_D?zOYڛ^4 *y/R}(|oV ϥb'debZ=)oGzZ˒?g%ڷ>sNυG>3cVz>j};W|+'Uݕ;dَտgH]jqL_L﹦3/\ukTevdoEL*{/?B;02 U_onߦt+Y53[/atEETSqz=nI ,޿jEwxNwp*U׼tޫnSk$m?FqޕU7ũ'g+r)g>M,xlc6?y4-r]j1^l&u܃-[D:0kn󖍂y\skܵQڵvˁY#uv]I_{#def;/568 н(8zE5/%"hT~*`y[{g/[W ղW0Kd-Еp;`Iu|t&C~Awqչhy gĴUse8 2oW{{r=/wZyHYÅkW׼uO@cSIE'm+$Hr?hrU]ݮ< LisX;ƶa*vkWV.8Q4-iy}W~qzݪpA@%Rm-+ +\g5LBھv{', U<%fǩ+y^+xe0T_-z͕>K'}fys>jO]'u{Eԥ[|Ry,YZ0[ٲP)VW#uLЮ¾[u/`<[z"=tvEս;>FkTf>n}`ڝ + +;m%ɮXQS?Eu49n|nZv<`X m>5]Fҕt.<&ل sSzcj5WMf 2]O˛ⅳmO ڽvU{Mj~N5o+\}d^ZӽhjԖ .=8k?kGW׷H_w璀ލ<3`fuɟ$*i9W3}:gx7.٣/:~3QpF&O![eB9;?[.&d#7[SVKyy3e;gONߪg0LyƳT$:qӶY(y^Fy˧'p&ʱPEsn7[?iB[-x~Rnk_]}iTǙGwgO.M/Qxd@9RwvYhBR7Or|~u Mݽ#o˹LjN[sW{5%K;{7?![iAt+:mn'g}a'v h7^[j͢o/l?Pٲęs386q3+8Ȓ}wb3 JT-nr ;~[F3sn[|:šc]'_o^%Wt3v+]jg%P3+zޯ\l?*-wR{&r|oRj+%&O+V3\,dS<< 7% +dXLa 0?{v5S)޳󨥩{͵4y͢/l +QϟgaUôݦOn.}45WEpU4Utvr$5E[ExEyj<sJ$92nu|A-v,'j_Y?*$jXOo8O>G_^@v cd(9aeW<]WW=zoڗfS[nԿs6IWh+Q8f(˽B>]u-ypkgYG7$WEɿj>g+ gr6~9_&~ei_羾zyY/ӏ-╓4f-*Cdu+7r:껊olagz7goz g+MV8Q Gܖ۱ts rw=P齧!T;,9r5$ݜ)%68gdt6GTYm,&vtb˻JoMX EWW|Vr3B\~˺(ܾ7I;nw;pG^pkB"6Tioq5=ϡFcOW=>705퓏k@m"ofNIevc.=RY*} ].oζX̘s@@u׭//سe2K~-kJ1z|xvI?cT#wod +m~FL_~g7ަlL[ڭe{˒w9-)?oyT>+Bm|wj#,ߪRI<)X5C*`}iuϷ7?LO D]o7emܧ/\e*F +Fgmb._nGk=/yIy[Tz36]և|ďm?^nжri筌#իfRjgW >wOpʼn%b[LwI;\㻍=ÌY +T|B nmzfE_ 4/yd#ěwjl{Xm_lk-iG󹕕at}όrCwosP G<*6s̅ h/m)Aq=_/>(}9 '[/DwS{ILHjiEݻ,_0s?137,}jj +m?:oϬntȳ@1Ƌ<29g~{X^x\-wnhs#gɞ:uqo=?˵y.{R]z~Ug鱺V- ~d0Zzj=񋧮?w>(5w.HmO~tX&cvSJ.l)q2U;c'%N]uxa;v9خFqԒ ['l +:jvJǿ2]+yQ_wYI'2t] +O=+-ww/Vxn_T%ERSkcŮ .]|Z6pyGlpsן7yX>#AGlqkU׌%qJ-{~f_sיTxuQE}gefwrBbfGڝF!> =ɐ[p`sz|Ꝺ}veN>wݞî` _LyywdҲϹ3 (v+r?E>9&r*jS7KSvvU+?s/#ˮQ-C/ ;![rrs.ix_onjMU~.:} -Qk\ݾN +Ǜk7֫,=w{Y_>l?^uJkw6dv>y9i|e;1uGtL޶w̩>zrü߮~vy̲ w=ΰfƹu.kylv9L9"[yUKԏt$τwdZO6\o3;nu=eO9m{S{<1ULw؆n_s:M*VNÆ9f׳Cܩ=5ɋX|^T.VoCog֌_ݍ8:k\9~2'pMPjlxHw?~aKuO`L_>(dXҚgVd[&+rArmN!ی)OwWǒ_uݍ%ͪ[v4Z9d隭'n~r +&_֏/䴴ӹ| +=hEm^w';35n9r[.o4]3ʼbjҭ?ϼdYkj 1vY Sɯͯݓ/X׎K17U\$/\Y<ʀ7IC{Ҷc3{1$=S`f#oo/5/zDR:yTRc3-+479V>鉝:sw[,deMPHbt\kbx{^}ok̙g{3_?g9|'7RŭS< +机c\\4遬Rw^uwḻw}b7'JɈc7|mYJR2C\nE֝^:Qֹ]:+fyw-K3 %sM>Ggs3BeJO >!s2Y>2%ק{ZMeҾzw[$n'Wl慗gƾo'OX+goSxI.,bZ} ϛ7(^75U^)K7xQN2չrmm9eɓϳ/aڹm 'ғ9o"{-l7/ʘsAڳo+ י$ǜGu@2O$3?^^sro)~<8|(g 4?.97eJkƇcuS*<+)ϱ-chz\l΂Pӫu'YnO}Rj[ߧ]x3>Ts6=a 32 +3KfxϛptiYϏdoز.Ѳܑ"Hn.޸in9kRO}Z#Y=+ON$fx,sv9]-pH}f.d*O}Zvť/rvlܴ7 /)tsu+Qk[*sPiZ'YG~ޞI.O6eYWeԞ,^l6!-S5[`4=gn\ķ^iHG)'eUou8夸:-Rn_Ú[SWdhmOY79:EoSf.zgm1qsSa8;w~oy\otOBړKLbVwv՟5/7X~rߥsopXlъ͖V \ *u^`lإ?yϒ|s7?#3xFO0-OSb O^?Sk,&#[23Ӎff=_$卒Bg9Svݗn{;Uu=9BYԥEi*6Q=~ŶV&N Zr\Jfגcx?M< [-5~^39k침8%m;FoDe'jbzB"v+QI=|ɒU Gݔ0z?ޜ?H2s<<6/:kgYr>1bon_wS9W9[aWgZlX?y헪w_~B8n;*_%YIΔO-tV_gպMJ3Kx(MaָЎVhVHs[PS¶C;1\ hz:Qxӹcթldh_cyΎ塿~\Z9 +]%[En:;Te훏bA/&Xr+±"4Վ?-9)߫3[KO2aqY3g9ku/?8Ծ+mzhyi~\@sջް:95mJV>`@ W:7M4mߔy9ѢYgP.CHMBS f1%eo=vfFoXd7 #Qw%]LM|cɈ%Zڛ=\Ҏ-+HI*3/VBG 7ӧ)7x24]sZ[&ϴ +MOU=&y[ArwF_?V8U;MҁCNW;MZq)GV֒99aM.Jr1߼iUjz/s,o:앚t%,}7O{RPtF{U M|opD¼?/|\&7!lұE8$ћRll|?S̭yr|~mS7r|ɭ r9SqOBе|ck2]~Ϸ$'iU Cnlu=]3=8h承|#>p쵼wik"WMS7CW2-xeQ*e,i#W,a&+Ԧgf1g9Ac[gDP̫pi=˫:ck4:λfjWF|Yםx˞,:]'og>6lVk?^]ҙ`3dΛU+秜\6ojÕc{֬ў,LvS_EϹʻ_`0k{A;6^fsX7VZXtoU%r;O8Z#yX*z6pezydɣm^^zB-#IɝBoO +[O{HqÂ9WX\p]{r 6:|w2{l\d7]5c}K/4*_-zEzq:&-=qgSUS^obP~sYsEf^\΍AuiYG9i Ş{>w1'|]ִMiNK^u$V976w[ԍm q K^_լsW+>ڹēo~#AܞC8qv*iN4 QRv3Sz +k'd|=itxY5P]FcZ矹_^~q~uN.u[ ov,L NY$vΪ TaZ>bDMyf9oը~?ՇW.k:m<{clϙl}p5ӓޓnw/v:Fuvv]xrT]j6.WRsunWzL4޼}I{ =x,OAm͖dEn +*T=TXyۊ~lZ+p!> +9 B'ԖL_=e7[woye֝_BSL^umZ Ȍ;_yVVLqM>Zɂ|gdSk&CݹۜOتSkǍ~v;ۚ/aҿ5{t|>ƻW)׿Kj + :.k`4+s7Z]Xg}>!w.JgRsK\b(ej&KIpWh yדeN6[&'ig&~q.-WU>l:y+!NEy{gu1:Q祉7{v κsou|f_m,(MڳvoUSmO枟t/wÇO=wA +m{L-+31.LbרQexk,O\(ukߥ7Ţ[{[u˻};w?μR؛V N.&ixy%.=MQ8]鐱|&ޛ +Wo-Csz:{sৰֵkυI|\nK;ܵ|_Nr7w=*8uatQ SO)&?ܙQӬE㫃8XYY1H U/_eC_;;fZ!XUk6& ++[5ݸ3qӍdj>sU^xhN៯IuIM tMm0?WSde JՆ72On{G?.lڴ6[ZU xl[~͖"!e WMJXq!$lgҋRz[2Ͻt 1]-Ҽ)/5e?Rt̿ulL lı"{zޝ}l3G4;@+GㆅNB-q>R^`׿3|ts$J>8*s؞|MkYm ,_9_}Q]3LUobץSz+t&^qmIlY zX|M^#aAz5ֳ7, 8dE)_eeݾc 5ߞ޷`)qpUDn_O;$?y4ߎ媓4Sv0l(H颙S/S,57 |yhocϯݸrtjfLֲEޑiE,9{n}`_.lac7TM=)D=CE>06M?ǔ;Y9>)fEӟ[94|yX||Ż<,Ց=x7oyO╕-7y Ux{7u՗g>-"W4Vuq{\ot3DiONoj9[+#~ܩ>474Q.l66:/陪bY'!2C ~8|ʖˎN.fvߗ?W~[ݴOodvrcסnvǞ e±\/מ-m E[[b['.>XGPRLCf|HUc|cnogLaz #jM[, sMo)eO(jq=d|c?e`PɼaӁ3R^ֹ0ͦlRJ|TwᄊVăϯ}w(L|ޮfKMoe'}4jnoQ 6]7]$;\NfQxW󵄃]}n.QkG9-u%Xd!%?;9팉w/Si34\앾5Q~Srͱ$!%'Bꊂ&ؙwm) ^kҁ?/Y=8fL-/+>S5rs>_ -E_PqI-ef铰qˇ֪L՗_꿤qvWVgްy>KDr$Tnw3|f6N<~-bߧJכ$[>M~9A49U wY\&+7rYsN+sl~϶ubUsՑ:wW::ovX@>5ST<@g +>8gMQI׷vZ,mYᖠs<ݘ'2)lz':rp؎S3Nb-oxpAb`qU4LYusw=z1la^Bc3=xųpibۍ)XNJ 0 9'^ƞ3#NmN[z \>%?:|^~) xӘ0w}G(5;o/N瞡!S{hBڝ3̹ShJ).!Wü ̏1:gn{?za[(dl>K*l&K(Oe;ly)rK}}{isUK>zwFcn[^^_vx ۣ?\v; V ՝˿k>b8{/("8_|ѴiV{'OeTPg/FeS}(Iۏ=ٔ튯G羶8}'y%9.Zr_I4.ic]ݦֽ\"ϥST޼b_re^Ӿ0:ymW ~%חJ=:!#hŌmfZqh9̎O;84Up +<)[8y|ﲛsFRp#jP}JNYTWJP>c}rl쐻Kf=Y^W%\is+m\λ`j49fK&5Z6w>nM|L#G;qْxm{^тzE<7>6fݕW} v=,oI>zuBu7ٮZ^'͆}=?#ԸWKny ]=t/ݛv~gkݻj?sߵfr_ ?ϴAXDk2jp}7z ~vesɩ/(ɫ&ww,gHlfT&ΖM<3'ݘi*wߗzEg;[.!_>11 V{.c\ +IߎDŽ9l:x=DIJ~$8AyHu:۟mU7'c_2{TlEGgNFvaKC S˲s*w\o*1TpSrsIvNoi/DqgzO]u5[b.~NvS>bBe۔&$.]nUm?_3aޗ6zBy}t3qTN-ȼ=[ *BJT}}42=~e-lo$ 3}uZ'2X۬3֣Y:#\җr*ܯs7-w$cB7!7eY ͥرܩ>oS7eb?paɷmBJv[VngFVr<7/9ɽj3* ƈTZɶiɞ{fwύ50 'ps$ձ#z1O);67ԛ[tT'i&Gϼn/_QeIS;wU Sz#x̖Vq˯:2ce&΋lZ^'Ks{M3l{+J<U=O@dڛs'yùXcqnN{#fMl<|aI_pLg ) x{z&n73+ozB+IϛuhpXkUs^Z/s&f `︛^` uco⛜E.IW^ޯf+r>aɍGO.:zqgsV8pް{$/]̯)yl M-&eYStU7_V˜ I(fXdZeIיJ Vn_x❔sz&LZXrΫOޔ<9 UONH<W6c:kݦŏ[o< ,,\Cb9H;wkgWZ[`85=k]gG7ǹU.)/9a{ʡ).V<{`MGC}O9Uq9ݼA*=bέ|vm${S9'.3z%$_|ʡVOwNV8rzLxzQG_Ҝh5 eF)[٭\}S~u6C 6'1<7q8-}F[!v]ʸO߶VJX--X%d8MSqy*{^ŒO/rݻxBbZ Y) +}e/Z +v.wa#kw=Q&iZ 't#fW*>G5Pv\.(ʡOʭߥk8z{^1_FȒr̼'~|WַMYg;ϙI^z#_쌄_lEoEda>;\ *&q<1vhj7'AS> ͼnLdL UZ@˃]׬n5ưtI?Ph">G8Mvd'q)۶m1.-vnY/V3\0g˟S^x2ER[B +ߪn|`-KtX}WtUEpyӫWï~U6 }H6kۙ]=]ھwe>[SfYr̍RP٬{;. ~t8.mν7j1F>blbP|#wGAѷ{%4},/+b ZKۿq~ +ۗ ܹks~qZBQH<.Yαi`:xEoɹS\b뵲GgAvY3m9[s#.|SWȺ{%HkS[3ѡ3r_nUIqs'}pӮ{}y˿HlnaYfmt{Ѵ0{o~;qE˟3Cjd3݋~IOxrf]~' +KEԽnx&p=F Nض\{'ڳ\ [.%j9p.uU)\-:-۞w-Q6/ xN_?k`}m.v6k3c/ݲk,_omߞռP)eFra΀ չވ)~Ue376]vÙ#v7J\?Xz2\b' S;a2mS2VYti\3vFX$H9O~*{gejmcZXtގIbۤTsϲhtZkY/M36kV[-믍0} M_쒏l3?#{ʵi%vn-R+8֊3X`Z4_YNڼQEXeٳ _/tavy˗38Tx}~p=VLcg]V7%7uVVrtgUb~ۤߦʖ}UI"SD>1~ll*KFUrPᫎS]qls+(%}Yх!znMSއyp^]i{]l }Wi&b LZU_zo C}5I++S0VJ[<͗vܹqwْ\s˧cO|F'>MM {^˟ZiVPRjmT)+_ş= _kV.9[޹soD\,|urT7B:̨}xI/ ^&,a[UV_a؍UuL0ܫMb/>ۙ} ) m~ n&l2d[ޯGs=p:%$|g5wz\2|]m]1v'o27 ;빐Nuw =5 La},%*sނԼkvcyZ#O/I(Z&BeNQ*GCfJKU ,ˎXz&ۼ$}[dŻ_yzbʋ;b]uñ9gk8$|񱙱E&O[ѱ\_^­z_ iO]dtFTocJuNN-jb Q>[xyS +y~W ױ_|M>l/_Bg>|!pym_d{sZxnܮ3[v&xɮ:v>wm_9hyliŦm?.sn|IJg5NV/z󒓞ˏ?r԰hv;o_Z}ٱ~ڪ7]9*zaE%Kz-aK[}]h#~=|q{j[붖=^'d, +D[ݯ_.Jk*_l٥=zK=ek$ӥWQ299%`b^鏫]M#g;8n7N<4\6XW',^}ؽ۽sOHtp0SNL3o}Nަk+jv4d\@%RŪ],fk_sko27[S&eٱ^L^8Wִ2\Vofr2*Ū3wkΛjs`wW.fm V-ұ&EzLM2gI7ћW%y5VmcIrR-eQqc[if2X^zX]>ת}gU׋-3bܽS٧{OSGAb{V^{R'|zjbdS"}Sr#OokZlAvLFV1E_y?r`UÅIϼ.?' +.;]:iP)F.aKgn|%dzGzɿu&ww~l?e#A-__v +}m+l\=߰0YVi2BOhy% \yBn3E4S)Y?yr35qY>Zl=uꗬ=1],ytGÎjI)Om(DV~˭sWomwML_@:x{\.pիi:C|976i^/ZLTRtB ke' 1'%X,U\|i+MKd?W˕-lw&Jj~VOsr{/@ctI_N_tiS_` `RM4oh6=/<0z57(6ٻ<#ӖG0_*ij'rhfُ | +u}Ƴ?%972p_\yFCꎻWfm,̱aRNۤ1h֢3۬*S[drQi_Q%]| +Z/jNgV}gTJ.6Q3m.^/P=}׺L웗|1iܾ8i6 x2C.l.kqCxg(-\Y}cY*_6_YybRL]jKW.jN,B-$cwn̻*yIr.M϶B|]M8rv_ztknW2Ci[T\{<[As|nԎ}^%#.pTM*r*rkSV|Ȳެr,,?ӲJTבSy5LKLZ3evvQ׵2%6)yf 4#g²y畜*uEo5KTyۺG>α9&iON1\bczΪiu\jʟƸod|g:P7G|Y7>uWe0'6&u +Nf%o&)Z<(Y0rQ[z$ox7ܵ~Cm|Y>ezI2oq7%Zs;_?qLUgʣ[njy? &^WMti?izLW[[LyzC)cM b|T5KW_e}VXvrFͺ,[pъeglN}ij3gEdvz2_aԯ8MUvrv ^)"ibjs +b2X.9vʡyAƓs0/Q~p[um[7?gg=+^hꦜ)6. j+jozŋ|?ܲ禮Si+Kzkb?gd(wLZ]M7^~5WƔɴ3{c+q,Zp.Wc-PF!jnۿoR)0w;ޙe_l*}?7zӇ?h.7`9kg}YY3GO)5\5(Y'',/==uy֮92UqHV\{fx;7Ҽj8kޟaIhHY\(w'.XP9QÞ'fUK]^~Xӆu]\Iؿ߻vjqss\]QdEsYL5$g\ecG-]jkʯL_ q%܄Gs\BW٢\Gto+ae.,&LȨ/3LKߺgq3^zAclUAI<|iڤ/'C{&ƬL,ިPrأٿ.qG2?y|& W:+/V5Lfo꙼#調߾m2zAT} Մ_ Y1DVOa}RmwƳ&}+%-#oT:kὧ G=Xmxbc)펓%+f.{7w5s׻?wsu_a㲍WzY|sΚ1wJf>7[G綪U?'xpy.?8f×77EsjcrSGGNmsO'ًi/蛫W^("Mr1Ęʼ=k\L=X|ߙ['[]?-^vUG\3f~9[-WWl, ٿ%~dJݹq蓫gWp<^{y}Oy%Q_y0Z3nqeϊ%,~}ߢ6]Y|3C}?*.8Ʉ ٦<1>eu5anMgv3I6wwϖ*b̏g^ͶdvYxt>Qv2vmfۅ/ EO)(ͪާK޸vv"v^Z\2=BC[&8-#V4q[?ʣ#MAXoIщ<Ljk8wFysn~D5F캱PcF??lQyȝi2V.F>m-Buv԰ LcK6{Msd^.0B gV>Z۠bW0ibZ)U2cli%9em}N8o8h·_^yԱ7})ʣΫg/{w6 ?ǜedC6^9Z_%3;>ڹt7Y/^kZ'#U7Lrމo_poȔ*z3S@oRxu>֟Y碳>hؿaF04UU"M#MTܳ!IuƱ_n)e:=KMˋ FO.>U{یusٚZb&)U/O|었8S&qWioX%eϻRxb*jrqYsrui=ۖۊJwX29+`%rvI NgXl:h>[ot?}g$U)>~ɮiKޜuUk8rECKe\~RemkhF/eUE_n<(Iqӭ~ ^WNVmͰG6<9ݦ(=оC抸5;ye8ߝ*+_I]Sx=W6~wgkCky*G6Bٳ&5·g}o8ERma3v/{5&7j/Skj?xhK;>koqTe.'-L<7응9=YF;KF:5BK5zmXt٫F-8~?{א_?]2W-.4bWv= ãGث!U=;ܛIڳ7_Efl,Ϙѡ=۾қ<-z]bE^o\~ĭS&OޠT=+X%XN?X˧"oޥ^|zͶeR6׮joֱszC~aoroݖ+{tuV|YU[x[H@=K% o)|gWL͢\=A;y[*2mop+{yw\\tv1M9\,kN.7^]ǯ;{o^m\2k_]Qnx"b>m ټXQKvOSإXv~ըû"e~9m0{Qfs1a,]4Opc./[ J*l0pҿ9֩{=< ij][4,fqc]b|o%7>ǯ[˾{Bv_yTt%[`sO]Y&oxIz[7j7}=}7/0:Ygk8CQN0:Ie6_◫oZ}˫WWFJH$ڷqWø^|ޭ1ʉ=̹šN齿vY%WD][LD4O5zɱߌm + XqC|͙t2J햿ggMXC5{sDlRf{ꗖBD{&MX[y*Rݚ(]*+W)qW=Hd'SZY佯K?_v.Ox婡Sm||`NS-vڄ6QiRM1KvvMcn>E#+ݏcM:¡܆.Z>zɕsf;u~R ezsOM38`GD/l^,KwA@|> :3ck7{}ت?o&'뎼1T]i#+.n ^vY"Vd+]?[.̾oT ؾLn"ǾkR.݊\NMk.g񺄉//8GKZ_:Dnnu$60M^5Gj}`kWǶ=8t[f=MqocmjJo5Gu峜_tmhO'JrRu=ŕ6^sust|Ewԉ8mri?޸Y6D6lf_~wݧ[1h;|џ;opS|N˓/( +<̃LGE玬o貫+|Z1ue Sr\Xsle꾃 Yص7a ۶խfYwe!/RdYvds>{P[}a]/Y$.ΛnW!iń˳?,pXe;w{?DIX!ģح3 ZoWqJf|ؚc9C͓=CNϵb_P574 #'F#̿'+gB"3׮g+#-벊}\9ؠѭy*ثH]ji鰤WDnZ's"nHh\kSec?ٛ{Ux-laׅ܊ʼ& o*/|oڗ=sz g9^k߼BO=rQvȜwM'2wbWT}U/d +7dⳙϼ1W~a?>3ċoezb5SG751e2r;ԎMzofnz2ix^^/XzTǥCbW +=UyuNv:u0 RcjxowNwI5 !飖OWqJa.z2/^ɡg U_حм})kVO݂ق,gecoٵݽy[$ytb_7T>Uרxjʡ?1+*Wiun~6Jߩ=~*晾E{Jo|3pl h(W9Kp8$YٌKXʶsN:=oBt +l`=7T\t$= xj>$r=MS-w"G\5fٟ/6ƶ{| hfnzsVi u_#g۳q)3z齷{RTRϾZho&U7nxƊɳF?:# ={agLٸ0\G <'kRH| KsUzyuPJB9USOlz-1X?L~QUo8]Tyrю^-|ܺ)7b.{"GG{/`gŇf +>y{O~͜{;VrQN\L*+ǫ=k;V2zBO^˓QWˢEG4r,ȶ]aVf*A~9 {_-2JMq[xƟogLsJӆ7TГ<^cY^;tY*Aךs v>VJw?8ze9'W}.`qx~\[r+O*3}oWVPx׳WTzSl:V}Ö B&3JSvX.8/qAHɯ2tun~O,BFyo}1{59&uk6eV+L漐mk~۟V:pAӦM67d l,@OFm]aw:=OΟOZt;RǞl (Xro_W-oKo4Q3Q2^p[ah6ɖ.7m߼7sbϼZ۶iC:͟jgNi=&uE3Um/SZ(]7,.~lͦĔMO9o~e֖kݙql}_|׾,+.uFHMgM>7)dͻp׎/'6kl (pj繳 +H/~>-t- #S,Rߢ#suK,4v~>3窯8<5yb}ӷকϨm}~Đ[iݶs_&n #=gu9f[;`yO9yl'JrԶ+]\NLqʼzǽvPl_=NTky~oO[$]\g]R\L}v2 +4iw^ȱR8_\RuJm6|Փ>̌[\~%vxO[u,ɍEW~fZ҂&N[bC?_:ݵ`or>]-]*Wt|(b:5sےP:νZj[yL:f뵜{mtRs֬w!zbY⦟8ɠp.+O6O +WE_39.~6յ+xγ +{o˭ΰ; :[o[ʍm~K~msYh*3szmn~5o3G:\궻);Xڛ%̖>QMxxԅgd?ϡ=]VE /1V}Òo)c?'_$$Wym "_r߹-w.O^|sk֚:ZAVKfep -_^zwֲ%W߸p_lqiMUk Xf:bzVrΓݻFuIG)-R]/OG'J<͛;W9˩U ؊MN;son<7mٽxኔKt;L \ВS= M˞-19GaͿS&6kNЛU'"iw+ ^uv|nƾ[ s +fOr֣|U8U[ԋ`>Ev٬x=Zxm¥B9T/iLY~jmj"_,L?c ̝'qjRه|<"bUjw8go?6SR'}v +^*񧳼SS#Lleտ~mf{lzVGo5kdk3mEY% +ފۺQo,{mʔ[1~ҙXb\hTCÝU&4䴉Y]]^4U9*r +K>x&&};N͜vzʄ$kAwvϛT4EݱS<]tPkˍ)Du/7ws(qvs>yEc̬y%\Dz=ϭ+gY5/?$BCKC4&- xa&>WzwΌ5tmsGiW>\*-Yjak .ؖ' quW}[u~rt Ӫj_q(}ܭ<[7wҲ8WL< 7b"NS}%%)iQr3[gw5+ͼVuq1߸s,1kjYǞ/;qKPş)9wsZV*'\ wұֵ/>{waav_xQ3i_WZƆg_^Ё<S/~tIgidP@ZҚZ1`w]\2W~Ӽ`^G{C|ys ޛ+<:G7%;s.~:RvqBfMLsqV:|[$oh9ySӢv0Wl5.3}V38\9Zv\p|F3;t)Y_=n-:_x_3 z*yx녉^Ho٘Q>x za7{]t&G\=kw_EuXs&J3lOU_%iO9t񺺍Rml]oL\ƅ7& -f &=S^Q]Uo{0k63>c~W~g N}.4x?E/- k_]ܹS~% 9%јvSi%|Ӟ}2^G/O9YI ǍfGɑvHn Y>Olr+UO^-&ϟYO 7S}ț׌ܿhZ6j-6̛qbqMwwhZ47[YP+a+ne^pry]Jkf>:}zOg˹g +j"GVϜVFT-u zzj?^X1_}%Zck^L_}4+XXVIL5:/=o~\EՓ7K2&ߔvϊw/%[utv$;[ )7w^?Ey笍om8&bYM{]-FʼxEzs3+H.mE%Kl]̎5ڰu[ml91;zs+x(ϸ©v_8iu ٬NnWtl?sU, K-e!oXoh\=~󋝶UIYJ_n฼eUaއLíE*7qثӺȭJ럨F;u1fxY{J5墒2s\UΩ֭=5 /L5Y~aa צ NH0tȮٯ>ʶ)T)v_n}V[ڜlQI۵4l3}im Jg(jM wڋIgUq +-+-6Ռ^Ulz"͉%m巤.e{d6uZK}^kW]+nkԖ%ZKI[+% 6rms̜͌3ko̩S>mMsvƵ+ۭ0^i5ڞ*mdOsP-~y峙x*yʅsu=~ְ_۷UFSwQv/KY[N-ZdHI4Tq8NH~4z]8.r6_SKO2o-gWEϮ鳿;n=^6|_pσ]7W|\ìyU+"j8Ѱ]mnvh'جr &Wxws-lj䭙+v嚬 j J(+^:%g>+~C «゜/kˬLlÕPNw_iwR|`@Q9u%OR~cb~R*b/߹2D}l׺uL5mŹez'Nh,°k}׻n.s[8~G99*z;<;-ZJ$ +7/duhyäK."x̾mhThqiEN%.ՈbN[ҰX{`yw̿KS국xivO]w'j~oL5$:λwW|E 3c}g[6Nۗ<>^^𼴯|եiڶ^]yIȜ;*lq ]}p_WIK\(ê˙L.g4a!tBG#x|j gm3Q3uog?PdODOzg7/y'i EnrLfr׬V1Ɣ_wik&囻b4f0r}.j#%VF]wfۙGɬ\slM]60=LN-]g\X5g*}dd#ݍSo=yUfc$R# =_mٕF/K\J|Q{=4vKa'QsX%]t/>vpj?zT..?=ygpq=we ^h8LT +'ƿB][yD$KWQQ/~}aZ}iԧ2v˺k$nii.&X'~ʄI?ͱ7qHKMWaW&+7Z\c9mj 'Kҩ^{^~N[6UlXsÚIT_|U]>0`K6OWָe̞r4ΧGʹ喡 )_94kaX?-[d}u + +~sR 1(7ponEl]+Wx{a"゚!rAE{`۹nkExz秶c^p?w w=߮q{ٱɲDeE}jbg(whAak?Vɂ͋_> +ئ3 K^v*j×w +Ϻmaq7_|VsAoHY^e-++?/Yq}I[ev(M:iMZA]Jnߏ疞5*7w*/|kN@}3'J\^)X_rf=/۲ozzK>G7M_Uw[\{J9p1K7M6#⃥ sS#\||>4Rf~ZxsOkn—\l4/TWn~#r"niMZ<_}"yWk~78{[Լ:,^T\6N}`ۏ:c_]6LBEes<4!Q  -XzZΩdf>s9]:tηnoIЕ۠ qlw.yĘ}ؕ[.?>S{kv߰վq4۪.?}8boxaM36}LWoe{?}]&w"ߪ~4MK:'!)J2%L>gkkzYqg>iVNH\?׾ +N\ż^yǏJ^gJ%$.svx/fߘuoӢwT=I4ü;ם+mnĠmvgh2.}d۲w'w_{l -/W +_dƴר㿓Ħx븽,-7IFџrs6 2b\욧CՅob nXnf;Vdy"S`ͧ+̗ )㥙衈yk%d'~1sprĭww}>ɓI&x:9+]\낹֮ūW_|~|TY?ʹ0#g̚'ؾsWR>]juVx쏷7[aЭaeNQZj-Eta.~b'3Y1c~9 UJ TO 8U-p{/ˉL ̛# /~EOx8C~'dVT?gs/^ +\}`^ה NȒxa,'|G`[iX, R+fPgmN^^׎k9qkb111ӫSvA;i8c`sɘec4 \RV)/xیD(DJk|-+!k2^{^_] ]7߳;Sz>2}xIY?E`υ׍ŧ*8}ۯ2l{b]0&qʫo9f鿫aݻ+^haӊI~7I=ظIY*sDL,Xi,ZuXq:ؽ6c8@×=MU7te :'& ~;qy^0k/5}?Uz: HksbD8^LnӆJu|4HйçV rmX*`[\V[\wnxdLU{V[Yf6pSRֺ _p\vfO>nՀ,̚Sxj@/nɖy8yכV[ljsErJ<س*pޚe̹TdXN,T4{o{g "ljtrDn}gd43rSCDkv즈E:6r7 sHʴswK_+V +Ι4}=*4crI[ +Iq8rG{Wtmvڕ8*l%* ӭ$.ƚ YMkK_<ީ\Ϯ~g>F)ӝz2Y?}28޿{Ś;/=ʶڏG}^pٌmcϐ\|=nl״gCWɨ^aqɃY®Q*7acJȫuJ3 'm5>^BAD + W -=ǻG*W_8?SIOi y6I旽Yc+-O=Rfc+6Ţ)ۙdqGt<67y3Ͼ+込*UϼEsF4sC[Sn +5{͡smk6 W6~,m5M/1xt`p9Ebu<6_R郋G%{v=ϳufu\l|;>[x~v${0mLL0&I|XϹj)˃w2}ߵM7tKrynu<|5aks.}WWti`QgS-?a~ߵ;ZjmͲ'U'f&s?\ؚ.io>1?[7^ǎW*Y:p$b E_|֪7_{F>JYER9Z%y]m +^U_Ś.8aDZlnJUt|ꯟ+Ϊ,) ץɞcMr|oywjw{k2]pke :L.Q.{1CV#}>60~`oަ=}HL$Ix/ˏ6mw _З(]bۺAtCVѺ/g<,SM7IYlRllw@'UHrեfgw>8>mwSDn޾lmf+o_5vRy7uuTX곙$DrjHJNqTp+Vm.,TԪ)gaD*GweQY[{C/1Mdbŵo;;4z Enӌgc>b_Un5ӪQ;e11:] +Ǖū}!<9k|62ل!3~ +ο}Ͼ=ڲQ&[v\6nCvKi,qb#TZJK9LI3Iz۫e^% >40K~W!rt77H~=r;sֶY+ro(]ԐOXd[o:Tiݮekg{.lq3Â×ڠ[nm 6WrPӻ2^ ԽϷu'R]mXn? jr*1ۼ$qք&畯^tVg=0:+lߵ#Ω\oqjqӛcBw}_hZQ&nWg|g;eXi^Nݻfֻ;+i}VR?D/\jXnukX'\X&ϥV+=-8XS0W'Gx%ǔYze/yϽ6n1E7ڇesߒ%*ѯ')GH}IIZ.\}۲4翟y4w祦}qq;;ZꝅmUs.Y|oݪbR}ðxޱ9+up#u^$qVM[pwB&>fX?`티~J|՛%6ϸpcM͏j{@A]ɍg-kXض>3cՔfޚdʷ?UbՎ{]{Vno;˟HMwIt ~?3Z#LQ +, g~󺖪=" ν/wH~wkEws/lF ;g/I-}y h/a?ONm{EA9ϳY˸ؓXT\9a5}رd=%6Ǫ/6+߱ ~v֬3*O||fٮԷzݝ&xZ<p*+V9oRx=rk%Q#uLwWjx<纗tV2RNn֌|Ejn /,xU2qfr ggWmy޿ړ'eN/{*y"a5I~ 6}[6q-o3mZS!yvS{J _D~ۋ2wo:CtmMcc}TOzKncK7U=ownwG99l,GUў \Z##f?QH,݃~J[{B l]U7аbR%÷{99tӐ/7dN򏟳z\ڒU·7w>e?p4Q{Ւ̒s?aůNy4|XR^?aUQҜP% _?,i'+ar?OquC|S̏/oe&9ĨNz$T~Q^1͗E< 8/AUĺOLq۷+L=9bf?kEw%geWl_x1L!7ފ**g]W+judOCD^.ϾkïI|,A} +{EknẫnƎTȆ dKu)\j)}gGd[V$qk`^ފ]ѲNJ&;_SR~RW8uSͭ׏?/ggls^_)csn½7El>7q},ӤS,%&2R>L uiY|4nLn&.CfŒ彷]3U]Fpp,Zk Ov\kZg'.hn5kJ¯T<*+ʑDUߞ_~̔^ + +:s}qQD`!f}CExjsa7r\XV$wt|׹w䖼N (ꊷasS4b{n?Yl6B,|-EEhI?=q;ȴȂ;9e֝zx +F]6F d:Q7LxChG &"%'^~!8lZ' /9VmJ⁦&evR챿kO惟tg4-;#s5gvH$mᜁnylo]P/nCg5I*UVOEIp2ddy1OGO-_tLΤ]nMz!}ғ Ė]8ڷ>Yumf GozIn~BדF^=>+(ZfmI̹9*\}O&y%͵' O[qݏ<$nS1l#y!wM_+[Pq)>HU>6ӕ+siTHd/[Es&^̝Q'zDoMկrߟ\nuͥwHn(ݹ%+cd_4XëW{J"vN|E=E1~Cchyh=)ČfM7ͳIJ9mD¯FF=oƩs}brꑭLm ,hLm3{@;{-Sozj[(q[58=BV4W/kRJ{wyOG9֙]1WyR|#z=ݖ+K'/`j`'}r-0S^W_Iݔf*|\WZ}3k~~!7kyr^͕Zx1JJmj3Ae?el7sWKҳD7&J(J/>)D9G% _FGOqew}fPR맘U +ker|3}CTsr|79R2YmgN;r+T]Ή{e<NJJ)#O*Nl&|x&I/`c#nvLd1ߠOirTn1ӎ. +{cwoZGoMhmMixuo^N`wѷ8vj'kӟg^wl+7̋̌<)!yXBx]u蚲3"wWf1KtaYr։휐VWSXd/eIQz^cJݝ9J/rͿ=8[D1I'־M~(֎2'vIJЙvƒ;"?O{JG=单OjsgIɽv ϶;nM{t͇ݷ +J)m{1aەpžmag_+r=L+zծpb%5ƿjf6n6m1%W$˶;v ["U[EJm"#2'| ]|-r9gr Z&s.U9eÛe&FoO +l_̲?sҖg[o97#kvkHYy\C]ɼ =KxZu_j7MlL/9y#[#+n?Jq[ںK=rF׫/z<ʃ㛅6ͨ3+(j߃3y}4u[LYZ8ND ) v(975'N"w󝷞DP?(~GlUVOi6-B2g{_tYe`UcU-d'>:Yxxk_}ZVmgx؝rx K~}IL'^|X?o̭֛U~s~) o&{,?L(77^-/خMtoy}Kms ξ=y-LGHNEk]sSA3*eyrW;e8AOaǵ>>=ۺ>9-}34tĻ Do`h}+%-iR{tm?^irt>.{ޢV8sݠ—K:K#vW^)ͪS-ǶލN//G jg=?mX&nWW Y[s?wkהo>H w2M}X'+M~fƆ}-ݼǷr+3M{YX|DŪYrwOR_K]km(}+tW~N1ƾSL/POFW>][Mn}^O;$o9̻n}4&W0c?h-6soQ{/ /U1[djwoQq9[HQ'V9Ҙiޔ+O).Ml}\Uv~~]g?l>(/׮gU Uװ9>sͽB?{c9iEսfޯ|}q^ 7f|T"#dT>`.xKMce>?ߡ,D㻓4 vKvɔwT߼ڗ,&W-a7B 㮨lyqŧL~l-\ۯtKkYxJrkt&>L8x-3;֍r*2^/kviZb:?KO\_,yrB̓l[/0H-ۑE[:yNmTKmu$pcc_7,W wWfɓk-_;=uW(''dvȪU-p3>q:(̤x;rs=k5O*9hpr [/{44o_˘o㑉Mՠ֡795$.1p-kw+8/'Ԗ?vD*iܜ]'Wu_%En뛇/ TkoY-9}:t4`] 7̷Uz(۬~OczLam+y[ B]e}􋒎KpYպ:di}WM*nVҡYBR1xrê`* #6]Q{Ud3)iط3N8H`\{+#/5>{ƫ-J ^}aegGlaޝ %ױ텮:om 1}Zŝ{eYr~CHN7VcznWZ9BE%o3JKk]\qbI}Z +fEѥ5Ve_~!+u]ym넶 m\}"z}fђgʹv{PkkZg ?*ӽ&ϙ4g],I'l.3HUbޣu/7?~ +>ӷ 6Jo+eۮǙ ޙEيN4?hDm~vt콬Y3X J2깫}+$ĔvD_-uR׺OZ] 6N|l$>ՖF+{.i꽿4}6KMb`pvhp}xi=;E>OntNǝXg6I?ku/erL侧'~NRY*G?'[ܿagέt2_,cQr뒥&Z)_|3lk?~lWk-jMwNg6Vχ/t˟933cΞQP'~|fϓOf42O<ӳs]={O_^;w. +yUtv͈'w~:{I.}]%& +S'L{z??e86:5]ld8*1hˡFv?dO0Ux9MG)%윥7=62g#>z5b?y)ʻlώ>R"gCc՜>=;<[_J|zߚ%ݻcpɳUO.dbbap=3? Rxt_^1uy>XOXzԃ66m75>>rrƮWYkp_;ʋVsp|u%nOmmSlީ:ce*ʟ|2f3u"Q[ʹd ̼_S4/Yfarٝo̪֘teĆ-ׂ Iz>`u?9/R)>~#O'ܳsnxl볇9#2y׮񔷜[KVp])p] +ωq0!=nc*εSX/cgso;2e+꧿}z&us --=n]YѬا;^Q(sMEBO gX&/jJZg®}n]\#uنve,}86GN eV~1ͽZ,Vq֋LV9񍝗A҃j9^`ȳ`~ePw˳E@yk߆eiA9O ?*57ەwgetVIUۗ=iOܓ]D{ߘn+^Wzw)oE.xUǂ,3K8S[M.9^wmjUkR +/:pvV~F9EI}Ⱦ,y6;Vsbָ^?ylSrSxEmF>LOTOh]"ղ0槢+% gb~5٦+el3&<>eI|U[-?rZ)X],诺59NY[$i?ֿuEcSD޷s轞r7s5;*Wkthg_FGFZ +wl<,OHҜ$7i&}ẒVo+-zQF7q*[/tRA7?-L;̿.q8SgFķfW>P[[$pF4c[WS"չ2FQG3 rI}^qUK|67˪UVWj E՝ 3kZege{e&ϒ=2sO=~] S%,u Oר+Vo8S&1aT^WfyЉ~=)就Qy+:?-.N]x1e;nٔcRb۳~ }ބmִl$?1yzɿw(kwm?vv﬿<\:{?sVkwXHq N~-_:K~N[W>_a>oe}O7f/;y}W:?^}y\œg NYn8cʸ&]70Gvu|ՉhZ4 +V- PjROw,o^75_U&&{䓯Ǣ'"v9OL\ҶPTm-|;S8#mnҶoߝyG%R7- Iuߕ K;gt5aYKqEW\N)zd(&?w] :}͢Ub']Co+ZuiZ#s/9>~tyC{"ۮ_"qҍ+ Վ'Q{P8e2Mᮩ ]z؃ZjMg>OOVϻwT5dۆ4f_0uQۧ}rʹx޲^E4Nx9#Nvn:X!1rjgF[07fhJ5߽^~&fȻ5uc.y2)K_]?cGՊ淶akϑUmsNHwIP><~i޿2b/[ּhOCpAe:S̤5E k}XiCbnLcy^Gl#e +21_9WiY+kkpEֻ~"P)8¾ӿal5.uyʷ VXޛPH>t{Xc鳦wD >cQ͗_ᔗ)/W_ʦ'K~$gߚU'w^x*e~uK VN{܃w TԻ<ҿQo TU}WqyNףwhf!F{W.|Xcr/[:bGLS9d{n3w2nnyuIwe{~t+{W3N-sRm*WVJCҖ`Ҭ.n +;U>~ƶWOwOjeY^yɎO78]DǾYO9W$0i#g#Xn)w0lh’i o^YkWIƳVmcuAq~mWéuS^ Ta\[oxq1U>Y bxB~_'=+QMvVܣSsvv_q{%5~˅,meTi/ϭhXQ{ʔ3-9ɳ5e +&6kxkVR٤v̜|e Ux;a#9W3h1Զ Z9g7oT()(ɟ^>̒D7:Nb.V} >uZ h!iWǻ6qyt.+w=):^KFNw }vC|SD6Ӭ\xyKC^0YhLυ;"eno]~M _{' \6trg*X6O(3S8&Ňejզ~iczOA/ch-$-!7'q&T7G&cLW*,/1US.e^$X_rxNAQUwW^^֔=3vMpƑ!YVZ/v^z +_gz_*p ˳/~^_6Po{i\W<6}"9B_gfS%YJ.gisc=omڕ?Ygyo:la:}'?474+wݲ? XuEnU`qV nK>-|J2[U_V +nLWeƍo}p) +e$35>ź{bzm}5ngyXcEZ'z7H448!X6JA_~_+L\mиn ]6x; yЮTRoTg_T[8,DywhTZ;؄3&x^y[킉e޻wDy\33d{759W08f>x^yG~Qy'iG#K +LW(xֳs{9[@o.g1#{Z!ۏOǔgMݐ´Yvkg 5o.ṸWef䊭IxpM5ZCUV+ʟ,5uh5ǬDշ\uT~_'+[~cZcgtZG3]jXh?9sO>nz~bvt{sPIwʔzB“ofΰ +o9X4O< +آؿ ZnbEUF.kHT>ŀk;KgO0g49mk|cӛ_F(x!U' Neay+VӐ]ih`޿{vXwf|ŵnn"Ug;[;˧"j~}mvS zއAKNMsX~Z⵻1ol Rso{1ڲJj;{V(kI +J]:Wg,bvZI"Cڲgkfߢ?cqSJ8Iڻخ)jZyfn>[=$&k>oӊe~qxo7mY~')iKuU_ä=ƶU{%wޢ |olg;YΊOܾI˛H4%eV;\NOH/V1t٬87wH޽\FurM"7y,pͨu s +Ӿ-t+d)+=sk3=SKzOtW^9_CkX`N}̉gN)۪Uc1Yex_\sYVl7gyk=qLk/w8nќS)%ˏb?!bi ^i rbU9sAqھe'_ +/"fU,r+o%$C}ˌq,m;?884g?Z<\Zqm8woRl 7 we{v`U+:n ;~v`wCOz0-ZdU3m<涟~?7*'T~GXm9m`f1 xRVZ\n~q,,SS*Q_9bel=rkJY_ >).\ݷi}3A+>y%cCǹ޿RqkfVP+\;3ie#j.Hp7'G,QSf,8xǸ#@yf3}jnzߴ~mm~T}.'2:lV%s&g(0s6}ms_rV5EYbAFgN8k١V*~r{̅ya'h=ayNىW[-攛Nyɩ!vycgU^k<˰FX6ӑ+a3.#~^S=<._@?L٭#xꔵUUjZHZ9o [5L +6(͏e;ߞU˲\Xk?\ko%ɟ9W]zoe<>N?mr9 E+Cm3y.Ѿ[tN$cW,xdHٸJWg9^Z9m%G~aۨ`%Um̃~l[`<7PIpF;8{/uʡE/U#e +D8+W1XNs(ϲ7M曰} bIcItmק}?'c7ͪ+~dl7msd2on׵pnȺx12֜ Zacls&5$Ζ_OMu{IPs5+|ǯKU?|Qܳ^~SiseC%.Z>Y:4,=R΢얚tf~ݝW}=~^b$hO=g^Wۮy-G/;_g_Ic;mbZs^ǻ[\GC'D  ӊjT\<#Vu-8r~LtYf'浪rO\q[bh7{f7J=ѳOV4?tnǒ5WO#կޒ!R6{ǹR_: Ml'Zh:#ue_.8evBӾ;_[jЯ*eQsk<;|Vi|~\f2Gtѫ5zO/"3QYΎ<vJuSo+CuoBR_ -r}J%7ɶ? -Z^6N)k3;i\+nUڪ[@s]*ЈySnΞX-Ki=牥"y|7Ӗ Y݈msp\~ O}cG_N>t+p|fִ}dYq}xF޳? ޵9ߩ9n;S.NvE 3VnM_g?pt+kLs}pk'd)~'/{G"Kzyr[gE yNH>4iAS{ _AǢۊNp⻧CK^Nتo~ڳ~6poU}[C3.D,<ǯw30IAemKJoٌ +L=Rgn?p&T0R)_P#yXpާvݍ|n }'CǾӗj1ԗ꼝H|gz/#u?KV_[8%W[s){O^7- L[3䔯3-[ w.N=W)}+[ڲ7ΜZpwzRBKEغcz/N㝲ԒKOe)/]&ḟ;vŒM]W_{~$+/vLmyH[vO%wmGn?ŀ+vwsٟ|ε0#]i$]P +Rɽ ߄T}G9ϻt2xƈO߳h =|I@oا5)'t~݊]W+kQ8"qGmN;KO~6z-ĎIfw< Zl&oJN]w&j 珬rsSFuvUsVn.|^;gI۰aZ `^]^o۴˕Yog}_8gmcZ")y?q~뷜y+#Y lxnb<2  ne}BuφV۶~.~IO›^ ax̶cxo(2`17Qr/To\-#O؟Z,J\KAuK.ٞ$Tb^ 9P };Yle:7ۧlu[+;W\3r5,'y,v(ʯKw"l#WfLzNFm_u8r{c~=ՂpyoU.)NLjf?:..wo\ȰH2L_(ˠQđQbǣےzZOlU\%W&.f"t^Q=IEΓ = M1Y,SqiwϮy:?nĮfʦK{>#IRlwâ23>x7yUeN_xmF&r*l~̲Z9WԌ_B$|PزQtQċַlfKzqu? g2zHUw(p;~ws|e'T!ww`f3WsJ٫ݸ2K&ӒM7V-䈞7=Cf)xBNx%__ٹ1=Ţ?Wؙ^~BU;dl̢vY~IKolDSw]Il^NmSmr*iĕt).\>~V¬8[%5/ա6)Gt So%/N8Nyੵg]J׫-2sŖ~)zeOižPy#+orXi͟?Md>chp襁;'E'&F|qd![޷!eɑKW|t|㞔 eΖ]13'/晴ͻvJU[so4s훌B>oҍZMh8ue"^ol6y;loWӱPqDnU}kn(9#Z$J͢o٘?Jo$.u/yѓ&~F6Yn1hqŒ2<$nN)pAL˦H\P>3o>O2h.4(Ka1;]8Z^ƲU[.[瑑Mv3T +_"GtNiX/돿O\zގ:%M«C\cq4k;L=IܧW4m_\ҹu}vOlqyYwkjyŸėetDg,*wW>ŰH-e09…[&Lb}3 zo.:ޓq^{MGX17_ڹ' |~S +6\~]{͆[昞y}7-j~D_wI%(}23pV7_q}t4}%E&gԧZ[o;:aN֬Շku?;V+Z8祾e5T6ޠ/CA㺽_oKi>2V=,wt{'xc;;,q7}}sLbc4$ޙ٧TfYn#&Vޱ6%բ3?~=ږK FE{z#{;n!ow- C} +6 ac֩>)i>s:IIp~kه{ox0Ke}i3LfdKNmA/ r9Z'p̨uK>kYv'i[ҿ|1|eI?ܺ3;}򅭓V>+uzozΣ^Ժebr}šmWH8]jYӬEhh|p⿽uzu{ ˺^R괪﮳='VU~>'f /[qօ ;qxv(קG=_XZOp/Ӵr~vf}+B\~5;ac&.R^dr,Sy[F#NgsgQ%-iydoo33徇YVOz޿`thya?S4}s?m?j8^\s6*vL狸dq;mc۫ ],Z.{љig6+:|}],/2*”kX$E2wb.ƭ1橌 X$|)is̷Q+Wz>·UX1X>ש-nc1>QjT/:({}:ň"&Vܴcmo|Xr\[%xOE ty绖@E< ڮ];}< >v*\ofe|.O +Fp-iuT8;|[r|Ԓ:WNw`Vwb:íZKȽ]cf\ٲMu[&ܪ_LQWFs̹ݡI';$b9m;~c-9tcIK>p?k=_o~,M9v!kJx}bCO/㎙pnuK/ϐnmu_g3ErEX| +j\,):tKӬW,dYݜEQdާn/~ƹ;Ny\m?5ݕh"|Yt>XRfZCYOc(T*+mNJeW&+4xUa燕%+z4/`Ss˲4a6n/n2uOKhVvT,f>oxosUc;=*KtI9pzJ%vv[,A}?[]d`LMy]TUM^&[^.Z ޘetSOoqGL^~َӓ=*wV0Ӿy+t krm->p,p\m +.߯Ėqu9+xZT׫^z֔3;$NlYfF} N6nA3m=,ZڟM19nLȭ=%{rMg'?[P11M,yH;esݯ6ęr M߄غL:wt0S9*'= ݡr^Aɮ/=?vK\Iܳ7ޔ4]FEͽ?(]\)7>苯μ-lE~:llWE W$8*rɴS%Z3.o.ku"g*nO)S/Ozhwk,}7;gz2w}PPȡ8Diw^QIV_׬]cn7*|heDyK3› WsgG'M "چZ&%-uO#w&~WggGSu2r*{.^v^hsg凎m54X׭{j֖g[',O'vW)z¥~HU{GylFϷ>b\ſ).mCoMhлcN6ݫN(~Uձ\K|ob~dN8lv}dgFL[gсsVfGely]{B7oV >h))dϿT6`|R9Sv㧋w^v/8wMoHELqie+ mSiVߙNicOy_uSǧO'9s⠙W.O֬K +繵RfWշ}b[{"9W:]&pYcb)vG/3~)P3IrÓrg]Z|nowW6$f|_wuK2rizse|q;7]jHLa}.foč/gm& )h߃>]m]z]ۖ*Nf*lZnI ˾gr^yD;RC9o^63csL{5"S%2+l8<1'5Gd??qF Gy6} _tLh{Nv}k?ٱs'Ń7)إarEa.XȸZ6jM~|>cee۳\AiL6;җkL$pn'S?Mx^O¾d^p;ٟ"qj: +9KE9.ܙԢ{#G^\`OMܝMCɫ\80O薔Q 8Z[Z4ϴMRԦ?6Sp7^]pVɜ;O}|ؠeRxڬAғ2.KoٴE]k{5Dy/zN/+M4f\q$.Vlޔ.oq01ЅsgmsȸruGýAŧgWjh:}?㾃|p7nz>-g噷}Zu~ejnWM\u>61ZUiDuL +OܦNO?~p͑TK\r.Sm N+65YE}:K1:{qt;KM*icitH6ɇˮ a4*欍{ުڪvM^,9zjci'xjJ2>I0aq|rv̉ 6ds="7  s .J7_Yu#gꇕ׳kLo=&fג)\}Itp|coŚL?VIm [)jIoiίsd/ +-l!`ɪ:6{gg_+Gf 0Þfw][3߃uJ.>̬PϝuJxɺKgrkS}Y``>۷[W=X-TYVxNhχ5cR7n/8g~c[ORV2i] {ۡ_Y!_2tx讓m7ޙVwY5ƣ~7kY^ʺJEAn-<Xdo5?x{U9nʧWK:ný +1J]gfk [&|xwܱ4i_u|/-U,7=zNe5FFN4+uf;o|֒i9̟IHX#*}.'wua%oLlfH'3ۨvV끇Wppjఴ߷qvoYhפuWnrI{SҙrjdNv{)~VbG"b/?8|7V +3qώC9;:oZ$tJC|Qps3&Vȿ)7?VάuT8uΗsMi11޻MbY7~O[=۟h3uOG5m7P~W@aF =m{XȜcʿ?rKOo˭wYߕ?SS#Vr.`S9أYRQ)$}d789bΛ ';'q^ 567MͳР—wnV:'jV#ׯ|d;mSIOyʙ^w{zp=9ȧMI YU7,x=/2Ŭ IǙhOk܁_9QPQ9s}:Ɔq6^ҲX؜]DWhXYow/wE0j[:O1QcrU}fFusxUoܿgzn^*^J'^6/YIGdPe +MpP~K٦“Px6?]xgwjNy⹧)~ӧsEt?g]f_w+a]M }3Mܽ~JwSO{/V{stVVj DXܖ0S:ׄ1JOwи[b1Oǫo/,h5Ln +g#6F;ʿ,}f[EtjK/is.('?c‚fn2TbٱχG~d7>m/f`L8;|o\7gd.LM2!N][͞vN~RvW>|?}SY7ߣ q՟#b_ ڨ׿}U,^y~pMݙ_fx}yw=kk'qMur$6!˜׈o]8*55SӇ;& ͬdNs]\<{ml{i77Ui՜Z&_&55tƝͬ\vJ& sRլo>=OZ %>k$]2IHEђy.4Kr;ےg!o+JN6N?bϏݝiװ3M`d}(έ,o}]>\}$%Rլ~A{EUuaG'4 쭵~Z)Խ}?\} DG ǧ~SnfA[]XR!cէ&E GPoH"wAV#~?_M+<{E}_%rX]gП)e}Y6aͧWcKxĒۏvnʞ)>3ra㶋73RO;usXxǗ< ~O{n{8kǶ9|}p1_19fu?ʡus{<˶Eh̭SHʔl^tjÙ,5BO>Q6 p%w9=ql35MY̡z%SmUL:73S0kwO2Tw/r>GcW_e<.06 b['?o6󷴨m$3aCg:lq4N "$&M V⯴Pss +E슟+p| aRk]z퍸~)a]\mG}GMQ~϶/}ȷNɳgO8v?SL (*/wbanٟҖq;ZAU3-ڭc=2UsLGZ[x$=pgZEf'7o.˴.7w=GeG9n-S*2 yu|7OxTT_,3m ?<,F.yjqG>O}Oer˶oi]rԥt>pL\m*?oM[Dq%.5Xd". {N뿐yldvWDuIK\|lLL]Y*\3sv/7c>~jsRZ-ZXO b[fAI 8!tQJŋe $|v7%'^JzezqbCL=vnfL>9)`$3%'}-vNaufw3'X~-#]RM +/_ܳ'-ŧJ~~Uy//u{ϐxz',d|r{%mL{Zܦ2ΨoilY$\v{Nn;<]1f/~qEŘ}LtZ[-vkk0-Tu7|{Kᒿ4\3:㚖Y4kWbk{tom|z=Іi3vV5T_W9GB>Nhƴ)}ϿE9 =N\(q鍒ε5I;dz9Ƌ3ɋ_?f5Ͽۛ*O]Y9߸IN?sm ןp8{\ُm~U-ped|άߔ%}4/OU[$#R+_;\#^xa՞2_Ko<[+ ?=Ħ ^7_vϞ ~4a-G`f[W6xLOe\gY\mT~gmGYދEo\wY|7~=gk,R?c蔧$./?k O䲂Ȉ;} +X.+)|c\\?ܪE,u2Qwލ5f;j-6c՚ /31ҜR.Ld[ G\J59!PC)+>.D"/{Iiܧ>kmw_>$LLtgT֟]ӣIY+*9ꮉgl|߾1곶'0L}>Nۧl܃/L=*w$2W׮hs^ӽcd;++qn`Nѿw{/ԑ,&v f8HͷmWw{^N#QOX-6z`hBqm?8Ȋ.oYWO8]]]%1*8E_R.~ke3U5UEmM=crIFN;V޽ԖW2_<̨ju[1ULqM"fܷ2'?S >65'41YegJ;}Iڻus ؖT*l&:pf]K];c SG% S$YjX^HVFuM'D˿'W*N=g؏6UNsT5mKǿ|VQ*0>W~n]rG:î&i2_g}__{'ߥyOcײŤNoO(MPԵg]d*EC ܻ~I8|%vyq;jJ^2{YV9No.Sxma7t']mxYkգ2-LчTY[\wڿc 3ulp>kתWьVҒ&Ҳ_8o^\ja|R~͕'Lyek͛n'VJ*ki{XZ5!b>wy@mLenSMrN?|gϿOnaom +,lUv>9'$Lݳt:1G7ϞY}sMV/JwOjWjWvṾ|vWhmC_rLD[ڒj5B/Zy;WdjoX O'سU^su/-8Aas~4( x%̉ V*zֻ8Aαֆ[9QzRy Kjr,:˰s|[w~8tG^9vqϛ]=ۇ s9)ughTl!G#g/8CN޼|?kE3[oVBV Mǡ篽oSS~OiijJⱛDfPpvU\kX BWU]Ó|}=ޟs'*'vlpb}e]50qW&[tE$$zWDUt([kLՈG蔦Hk">Y&^˝Su)o>~ֶp?uLoFŅ}L17j:=[>?UarlwlEZҎC",»g|2_\u񇢠>]2'&n?\׷Τ՟hbʟO6XݧV>3y{zNOc,X)7};ј}0!ؽ=~vϊ\}7-9;c{JC- iW[p(Ѫ o&,kob7^q3r:W~ؾZׯ,+{ԲiNH_TyE?wo=X)fߗWh_<pG;~7U:^XU4ojר޲/1*w#XMWU nMbDۺ?>yia^qU~Ռzg]Iޞ5{;&:}aka銪م{(8zvgYYV/5gcg%xQ^%3 *n=W5тQ]~jw>=QZ $;EfY0d(8K~EZD^Z>\Au| [4G^Ħ6 ^鬼6D3^m~It[ùZ^pU*2$V3lW4۲va?6C<,hq}o)#-uW4R\=/HuڏIe+n[^bۖWپZmޭvr\vOͦrUg.)+~},mRns>#)U`Yyw_gnepO벲ޯ~wY9Jʡ+ aUZAI~E7/WS.2!qmWJy~F^uQ"~xfڒ)xgQYKt鵔_xmTHA&NgsKU/# +[=zӥ.OS~cq2Gu]ԹOu}Xg2$IiE_Ҝ;yU-bn_tρaйumNek.Ыgl ^[3`sW #Tw?/v޵doްRޛB%E\wxeٖq}؝d5rEnv͖-{?H||a`K6u Inwf$S~t}e/ף<=_ˑQgX.|U}˚l\ *9Mc{Vd8Sa<4{bC3%e3VNQ1w^xK'Hqh">7H+yKi?9 +%B-[BS))s1M=믪=N߾QXcuƚ +⾭g}Ҝof]Vyh EmqQ1QCʼn\]Z^{#}e~Nw$P {kjEϻ%"2?68+|jsV^qz&Z7k)؛cQʳs~[[lRun?T,p> MUD$jG%.EWLںf;_7_F<뜘Ã+J%z=KL&嬆=?=g޻6T^ћs&g[O&YW*=.Ҝ%眮ŵM˱KxAnZ)wMNT&;Ed;4f%uy5!׎,08HT0:y ڿt-Ҵ:Ǯt=.-;K|@;gsR>I(:m|k *Lh]Z p'7?o`:󌎃)U/e-p^:OuV%W,һoTxfYK '28.;L?Sx??U)Dx 1v zuۙX.w<Ͻl=m/[&S~Z Ɠx 1}Y+$z~R١m?#U [3{ԎOJ 6˝eP[lRok"Cq)= S%9v\( k1ݚ[)OĞ-.ZhSs皭Xf.-G/w$*yf[LhGvgSwˇr1d=[cj_L| +S%Wt^!v5(,ߵ!ޫ;fֽou|U!oz}m?l1iz!1E摻 *mR:$Cx}j =1?nYZ|==~4O#Q~lM):rQcI`$b#ϰ\#wNӫ<9pm/CwB +V8׿8g670uųo=4'r[WZoXx͂gbӟf00=[:Y5=o01m_S/Uo^a_~~ٞ{;oo +V޽3'xiؖ*G m<'VtQ]_ jo<=ڴ5^W}w&܉7z_˹|bAas=S$^Q⿢?i ?&N ϽY4c9voSYv"w{t(>#6@;^<$-= ?uoTΤgB_U̹^+<8SaeW\(ju9X*[G̼Uq]/[w尢_ovu63mb{ K|y51\X!Oؒtdz'3r}ZϗjqC/?~&dE#wŧqwgR^7 /'pK뮣.:=&˼.>^QFxbae!k59^[gy_ ۯ,F}\C}Zuք>_F\K+Y?'H3*6^SCq2㿞)e +y VL1m:isy);O(;}:Or ޺>x]o+Sl>==B<(pKKΕ5( k3U?:ncd3]}Dn+{K~4H3Գ řw켿I)_/*_<`(!-D2xn{UY?]bVHIZgt޳}V[~~?Eo;}Ԑlz&Qe'%?Wr9urF .Tھy!jj\u3n'l.y"|Ԟ-]?|8pcĭސ㟣ooxi} t{Tws9VRKn|Q->Ƽ{ˣշ#b7kc9gri|#Y¬v0@RIHyXqfN~&bzUwZ='tw-cm]VweNTt|*=r_bcӏg}~?)H2v2/UhrZmj6G ;0xګ&oz4]r|&D~S6?Fg]/ kLieoB0L=WgKcw Oi=9MN_DVK&=q?H +x姶!j̪}-Yw1ӺmDJo)I&JLuO7N[$, S!L8E!,{M~ fYy;1~ K3Ϲ"!8`{(zO_LJ/E<_}7KJ/L:6޷EzJ-^%Ylos% ܸ"nKDYwOs"nc=lmZuWRv1Վj}[^gբ}ů+[=^ݴz+- +Y=Ϲܓpouے[g-=A%]hWsA{tU>]#S}D?Ģ9+/tɕn|j\j*-w_ݜZbPT)hhfRU~}T,5A&<w8Gf-jWJlV7HjkzcCɵ (W3ePvBߘ`[*+|ަz̕sn+2jUϺ6}mgE-R 3zSu9N¬y֡]@7r>U+xk 0t._m`ny'T˒'d9K>iy'(h'/hI⋌RbUeVd +bpę(nv &_<.%ƿc.4ۚ;=&|Ù,/}uf&Os#{nɋ&ߓ.b탃 Z?le2??Mr/ӠePב` mg>m<Εg3Y\FMnA?yyo_2nU1q~|QnAvO6|9y7ts>Pm.w6H?w>.O¦ϱM5dB߬tX4c )&6]97qSLVCZ4‘(CO=?/ֲ>4}3i}+:Xqs۬>cFBSmńcw|7]-uΰJˤ5mdTm>TdqIUO^oܕ9webXѿ~~5&(ͪ~Uz}g>f*ۆ,;KUho;Ůs=K*{7\fvxҦN,ǝr۶8Ol?Aٖ7O| 쾒z=6-i:IkɫOo̼)%AO"k}1ǟPGnl_?.6x]bY%C+8m+WI_T,H?3[Oܫ~\q nYϕ/] +8:-u+>[sA3f3^ڽV5v,Yo+V&dעoW}/e=Gʜ3->Lg6<_cӛ{Z*bmϡ셀l~Pm7;na^hQik/5w~{7Os/5{iy˺m9jߚuߌTn4 /mӺu^ˁẊ>?YMjK;^=*5 O\Vm3j_c'2Ӑ8ovX,bwMVlb梕wu=xCwvw"~fD_4x9_xvTù]Ÿ]Q{Uk'ɕ\iz?r\f{|_E=.3zk;gF+'^xNjƧ[vyh#{܉S%#v-{}v_˯]hЅiº{ox^%cq F|9;?DM;-!~u G{E{ \g}|E QnCo%ͼq::j߻Q@\<;T<7{ՍYu7X\s/0tĜ[ŗkUҸ^~^Ti6)oN n80=Ab9|gήWp̛۹%?|Y)v[X`j~P͆ Ug1?t郠gV{Y+x+TU|ÁσBmqsfG6K,Ih^,yڷnU+< +|^IϽf+]4kѥscMy7~`dR3S5Mcߔw]pX +)LӮ<|9e}<;n'%Y9OKNNbYpL˲_ +ynDZI[<6~tɔԞ[k;n=yIbϥ%~_NzyjEH5{9ug2 ۩<󀇹^ܻCnr?rƟXEcMm\"Jonywۍ{jsC,s?ZzgY/TgH6]EtX2:O0^s)Ӣf2bsZveYj?3e=gz:7vCdN>~+Ywʧ%''Sq4Jy-weY=uZԗ6l^SQ[V:mJZk6tʊ[Gξ{~wUQ3]v.C"[aA%; )&gem8Åmt\V薬~73g=Ph}jK5ݩM?r^:+;Xz༾~ie6{V^}qtnL{~JV/+_$UrI𫊟OKHVn;CT#c~-X}#VLfgGsv6.s@W+s&xYg(~+Ye_s U,m tuO%5y_w;.@M)4dtbpyDAl͝!~}> 6m5o{h.iIrm9Ǫl_8ݞ)<%)xt_-|qAuGԊ8PZaA k0/5}7/#rSs&y: +_9o):!?˩O'҃#mW}TW0EUvwOwi{ krT:ps<ZU)spS/VX?u_Ig٢U,3bF'Ӟw>f2yEd*mqƤܣ^N354w?^ɜdvV(65iAn{9gɘBşVF7D|6t)ǻs[{ WːIuWjGtW{{axm>SW{ct_}z~γDZ|baE뗞RwOyR%kSNo]W_6?s+ +Kh8Rdǫ;l_v(fMθVU~gNv+>øA_ji;qAWַҟ([&!pմUm\Ty W0i輟~[SJ!隡sͣس8FrqI_Ʈ$5-O0E' ĩz`ՍE,dZ/:{?NUݷ*/Nv-!%T(b ?ycQrZdm =ۿr{tdžu'Py>-\;S0 ne^ݰL¤riE y2yFƵouoɺxz*|{;nG?mvksUhX׳9t~9+q|yP~ə{q*̳\|^*LuʰQf7ycɬz,ɿwh8>InY1k>l}L :Y|/yM\BkcVز Y#C4\hfgymzѤ[[v3 9#*ƕILXAvґ%-~h[e=7wG?8=F՞2ļ[uC/l~ɹ(ruQ&.F!זb9voGA_]py:oB$SK-_Y:3ֺyՖSuxEl>ǿˢ;'yᰎl7sZKtn8&p_~hzo$^JS= |[52K7u,3ڶኘxE4m+w}cYqT#~_w̾s~.]<ӟG s/HToط5q=obg(wy=k_Wd?y{US]P$ps "#U7O?l03bri.ou+S3,88m촲ܣQZrZy7k_睧ۅmq^'yG LEΓl9bo[@3fϊ +'y$ovc0 ~ +{L_&~OjIpΰfȸ.k>g^ι2'GУ>uiy*.ah|msj;[D'}jyrurīpjBw7o;i2Sy~ oH-&Cүfi?8ug֏+?^e(oÆ&*r\sğ*˥1~oǭv d{t/])~r~ًε@s%KNj]2)S԰7V4^yͶq,7V:s%WO7č+;Ֆ|y͈{m;mot{:kl5俥zî_fV96ПWE2H -j$j~ۼg/S%Zۻu^w)QIW"S68i֝+4_x}j|ɶ#5/.]zszI.|/K4bɟ{o@/>g߈n6C)߃7PNStlͱQLDž>U'}W^-ɝʹb?mr([t'=ճ>;IJ/!39&_&'+}EDGz>?;vGlP,?Hbws}9c:ͺ(14ۂe[;gaNv{l¦Pfߝ<*F-鉚.sNg稯fnBB|׳3* 5*#tJ5~[.ڪ3yEO_)߳)tWarܳni 68mD6#?X~fV܍uņ?m,K')G0{%I1MƼӎ|Qx}:VUNId7|m% kXRb^`v m G5_zλ*suT+[6 +&yqռٷ왅~ _οIIlJ^g˚gj]>os!.9#}'Kyw^x?{ɥMӢԮL~gw87JNj^ /ukg&scZ:cg*}yF&.΋w}QceowO{Ph _{xW{r2G`͟OKg:j1ݳ[qtם]{Ғ;yOL- ض1k.sӝ|J'yۭ{Wl0ӥZ/wrj[7-v\Losw[kT{Lv5gg˾o>u[t|^@5;^YgN;_9lK6um?5g;oO_]^aG͛|jYTշ8\Zeyp5' ;/M>~kk"Y>Y9֝0#v:-ܡҹnD6~>;>狟t}3|1J_ý l>Ϋ/ O}Z9рOډ+,m7Fv.<Ƭ)<3M|=efgoUm s<@rڮ3O;m/yx~U7BiD +ٸ5-/h wnVL :- ŏ~s ]!o?@]vCM^gSйB*9Hl$x9Ltb{髓/1BYGߝRK>Nn +W͋ +|bZݷ3Ue+sT^߹wTiN]oʞ/:~ɕ3/}ȷy[~/?}j=W&S<Sr\>|i䪾-J%|Vxhؘ4IRwO3ܚoX!~nOU-ι x_f%[_H^hS/ܒS/#z5\G1pfSs7;q)j]uמʺŵ?ycŐ}ߔ+< ,Z.cm~-qJAb_ 26r>|-#>9w{Gs+"*bjE~_E6^:5|6#y%RnߢiJ̍;e7}s~>^>y:ÁW_xlּR5H&W֎U%.^7kuk/;!|P~_vM=aA#A֩ǎ xKfed +]?fn{ϊ$KיKķ&ggqzx~_&I*+.4%/LO̗߳듴neyZFB Ҏ]ʬ2SJx|cedKmb!$jѪ[ѳ x\uĴe)S7̋npdۻq?R) +乳PN7)FulYWpv?$Ֆ irH\w7KjvߋoP]+sijPWt4o7b|am[BozSOywlh\,|'c?lK3xETkB Go̊w&/x˿FyMvu)oՕ3v;A]Eh_ّc Kؗw^6aF, qڪO.xNJӻmg, . s}4?홡6kӖD Ke+T6xM8WY^>5D%IbwVB'ڰbZS׿8ڷ=zSl8J<6|މEG'"P3ҚxĴ)^rkmO,#/Qsm}]l'*hq<$WyCQ)m,!>Dv S /Oof|b-v9Ŷ +ǿXUŰipԾة쑚V o}6MKn0 +)9gU}Y[-?[(3=ҟ>6OUPaw|!;冼AK/y9CV~b$NYŗ&U*mtYOܼE;lۑ-Z–$N8ywu\Vym ;'{(=,,t-[-`?aދ3ZqgML]pܶ0_C^+gsySǔׯtҍ/x/ +!䢯_<jяA RrL?Zo7U˿p].v4QqN[ɿ x=ETFxgsmFރ _'Z`dJ_"6jFnk!ǷsgW xeM>:\mUyO/P7r)a}?~6W0_̭/ZYk_qauT^DUToYֿmun\iT|蝫,Rӕ?ULQ_yϔ6Jם}td˟3cOjgvsX,ni UΊ}/,J*4y?c- |gu/"E_wXv0tf,r87ƽz?rl$Okj;db[do/3}Ŷr.kMm֬9dE5rLV~'߃]ߜMv[u6_RS#w㽫i,( ?N9Dz#u\A@]7QQӑx޺m*2h&%wKUtS<hԶEK#^s4\:no%ە$yT/ /Bcz%oҋvʼZ㓬<ؼ+CgMbΎo+mwadRk3]9F8"F{qo rYgKE"z-~(#Z;OϷ໫U- hNco3|מ(Q<߼s7_wN'ߝg/ou(y~ G.Hb]8_FܚeYS؛8ݼ*]([Θ9xpoz+˙sq˱1ox.fɑD̓k_frl{V?&7'OBK swҠKޞۻ#+õ)*|?ך\6?#\8KjV|wlDBIycw^rMۧ%NsuC4| ݕ}V/~3ůgo^~=ycڳ%3N]4zңq87F>ZX#%٘SS&.Y~}?]`y}ۋ}'_z^z} w#,?Л*VvNjgzz)99G|'˯FwÂ:ԶjVNW/FzHW:W]nj LgV,zxM7?egnGG[);jΉou*7}hmzcfC>ص%rkGy9M?7HTwzpҰ6aʞfg,RetEVOڲ܂E4K"oKXsͱ߯jZΜqL'cozϘX-/;|o|JP^ȦYlYΘ~F1YaGsj[ s w{|}&E>ZlnwT۴eM +ɞ]%]$[XdG*M %sF$or-7ήUi +X!(@OcMW&X)yЂngiǟFLsњ&onP{{Y[ySL_Ox|@G9bZ5bvO&|*TPdI⃵96G6dzHOoMhj2w}=g +#VOyt(z3߿dyg1fzJ?HЎA1WwWBpM)6VKȺūX9/=(g8ez[{qxkߥZvK Ty>5Sԋ:×_MwSݳkrW¿}{Z]DYB65qlݲkabג# j6Dl>,yk֧9sB4/W[h돥q*TRپuQ/::Zyg>ȲϜoc C:S7^d#~ƕ{I+0ŝ|V;:&-Oq,ݸ /5P2ÃMKVewyFf-ǕgE_}9{_nUZ{M ȄCSW'kexlu̬9-C. .OHaA9Sԑ._)gUcc~IV;eWν+-'K5%y5}M?˟p_ᇌ Җeic+9/\8\ێ ;\_|y R'c뭜<&vHf2ImM56pm^!kk['ܓ.>O-:~YklKܴJ[RSoi7զ?53v%"rI2s/qh.ewWȱ<>a%9Kce_5XcZ61te^u_+3š;8K?fq⳧5Nq_xYhX݊zϞ3,oMyjtz]NsQBߒ9pJxڙ7B>P>r~">{rb엲=LJYrɮ`wsߴkoؘ o=2|/nQMkR[u|ۏ+T4,Thסx][럏o|w^fݖ'v\VfMFNKZ1Z~ۢZ8CRѺ2/(m|ξ%ue[}e!L+\w_/_roj{[g.`X|cw+&ms(T~.S&e>Kt;?{;,Dz$w~'n?yqqaF램kBNwR3@Iz:<|>:KVxu)c3G5E.l#V}sU}7Y:_ o,t#Sy͢)kşڼ +>쿦2CnQ"g&Cy!Ӳ͝'~Ov]K|~rG wG ?I]>Ipٍu5ϟTU78ɲvSS22OUd 4aW]S|䟟|W*{z:m73,߷[.ob_RUI~e̚ Ӯsl.k-xw>v%}g] /?7s#e*g]+]%gDC^WZ~?y9ܾ9)48-ږR鶈^jdzxVSʞy&W?rLJ"F\z-&*2A>5y5Gw3qn惫?F;3;-E.>`[&x?5I[= R|YkC~Vyw$o~2I_̼xgi,$Qh6O-o9'kI7L]U@mW7I]J_)|{7Xab3gM[2g9·8wu5W81&c5WWˮ+|ī(1q.G8wtؑ+>|[/xz[[᝽rrNxL<|Bg̃M^Lɰo)K=(P][ zBm]/݌NZj0SE'j +7Dj4xt;}\Wdߛ\c$oK`)k:&1L_[n*_o3;21[ϊ_k49hp\b^9S%׷5d}b_REm-xgSj7H NbxuƓ +`|`KC9gO_9ld9+jҹg8߶s޷ hdO*w NZow1(m.P"y np\$p5bqjgMW,Ob[۞㒘CS-pBН7,sBښܐw۾dp)-|jmL뷛wF >Z7\D$ݗO8վ;2\H~gu-O9jE_fE_¼Ry~x{0}i"vQ[Y bXxw&O!n{='3U7jYFgsM_[c&m \pA{* ⌇ZNH(L5Y:&kNU\`Rsy?+fo4*浯{5ur.X(=թ w\ZQ]M.!#d)O4,Vs4gY3!e-cK3s閔 :EJ=\㛉?i'fwpss^蜛T&'KR yUosE?g4Bu/@G +l.{y3oY2ۦYשЉ/ʬl匳z~zQ²?z"τ՛ӧğw|uoLhm]6?u=Kj<`7_:}׽L6s~FsHn^%bK}Fްmm +_ﺌ?7~Yj{ьOOwrEN,_@W4INև?X*2L$e[t3e=y|ofİr_L6 oմ=wxNU'J} ;+>i<1O>=UsŔewO7ss\᰼.ZAx]XLG' {k-7xDKOo[eݯ-YGo]O6lm0Ή>b̪ Gk3@c݅ѫ 7rFbY*\Z2q{sY'or/qir})Bsq74t+%[\_u<Ʋۏg?*2KuVogprm$.yj}pi߁Y7bPSc)cs[ woKldۨṗ\ҹtc}/k/k=9}ʄETT + c9LGU}n~xuKC+vʯ:䴻U˄3KMs378fwuBeQ_̷]:RG˻-㽮(Ayk[ͽſjҏ~9ZM*qҒ[o:{r;WJ_/o>%rѓՂGĞ[^YK&}#EM^pzì_ם9\\X_Yoܾ5t7"ΝӤmsgl4ziTiKτLU-j5Iy},U(ZXc/Y*Bo_߳nɝ&c +t˷lpzz|#L߸Sխ-3}MGp]iݓ3Yz; MXeFC|5-[6!/;|2Su}?9Lqh݂Oy-< } w]sE:6w*ɋnvޙiĩ򭿉^{-s)Jދ m<\yyS󂿌)λq& L0QW"`=ߖƩy͝0?VQmxog#9Ov|(;޽'>OM_,ZP,ǵՆ^!a~}VWl^c5%"ӱI[^2o9쳼fuYGJ7ɝ23輹LWsfr^]-Nm8UOͩ6u4XB{l9)yY8X|#1KX]yWUcYӯlmn +зW{I;%vU{Oϩ {W w p!VߑʪoMd_{N.k 8\_\i[J`ozwųdnxa}\:K;}|{}8[3=!v 7^T۹~Qb;ϼk z(uK D:aҿFW,}YqH>O/oeSVafoؗ:`kuW,_b5Ni}t6@_[42. +}RmPYjWg 4wol4.dޥߖ͈L.vGTR 7^K!󅈣$_/95wkFFQ1>݉>e9k'Vo/2]^ŷB;^j* 1W'Wŵ(gkM9 +';]+GxAǿ9n cM{Ӻ9Ńvo~(^%ˤ;e#Q.eܻ.nX )'Ds_Ml=*vk;S}z5n&z[[ =vk}!/bj%է~f̒'.I7~v/j~XmʸWhF|՗hYH֥kHas{K/YmY}2\^w5lsy({ .[ ;ۛ1(MK>bŪDWN|mǾiyFNȡ%%Yd8gqGRYǎݝ9X:[U+_Pw?\p/GzZE]|'{bˇ׎I+gٯcalf],X&Z!s,3ͫWHh-zWq=8Jޞ-gпHd`!9m-٪U::.{egrڔ}1^b1҇~ݫ}[BMXt"v~1ãΟ\Y:\U"?IOfyC%K^hxlo}ʋ_?9˪ͧNJ +~HX_c\XbY1OOu+aNQϷ]v}m>f@+'dqڼq'zf7+&\J.`qz놨/7&3~\Jņ˳|dB6q<_?NY;e@3*gGՉlz<{1c;Yڌ5jTɴ텽S^HT7ǮQVKH(=cv Kla设z"c_m/ZAcF`~t1Gl}ޙѶ|>y߱9ymߡy]6nwǂ+]\$U]^+qLoּ}ԧne*vOE`;oK//m9|ok+SʘDkkv||yS ¦&n n:#y/k6OuavÓ3:8wٓs㷝Ss3mubF:y~s87پ_MlPE^A-ǵoxaiS7֬4֝[?[]Wn%puڕNsI?xΉ{X ^|Z4,}Ϊ)9x촖SsZziI}bH~mӕe:smX!ܸU[t3~I/h2Dvm謈h9wbݚٸL`<`GyWiehlf~ìU[S_0iS%/k>>_ IJ; +Lwŝ,zGGy:DkYΟ{#Sȣ~c}֕G"D] O}G:؞ʱt}o{èKڳ?f=}19|<緇}Wi/a3r4r:O8Q{y]g'^l +yiҊD?z] +*4['tZvƏiܒB~a*q>şu9}ӽ_uڡssWCМ֑g]6g_1۷^2{;QF_߻o㜽MKbXAScq*[9_|T:ˉ'x}gK.Jݟaø=?۪F֝umNp +ӇY+7yynܲ,IKYTy:Q_>JS@͟)ֿ5^'z6Rmpnv7_%Yk{ZWwԉ#_Ei~]WJDmJ -9- I'驱o6V(;̚oJWͻ3 ˿!Z@Ҷ7U%*+f!;obz~2"G{sÎC:W+OX3\xtx.9[mKm~&-*akZL:Ox_;uBc‚I}~,65M{WSj%6OYϘSY7ߎ ->(NScf7~JsEjԳmTWw]N?e/dyVMR3Kng{ua×bLUulN\*daA`znY[|7F?|ae9ϻ{Rx0ﴣ +s#dUOW 9b0u5$ ԸRf6?mgH +zM]1_m:i/{Fy78dֽ_k<q8,&( m E޿qaf}ݧ3ї-! {yY8_R":f+s_;w5w:UkN1OzL_ݭfWe}8#ɻw UQ_~8'svr;l6y!K>hWyE?-)~m=%Q7tO39>Od½}̒nwv7Ù=!sLb|W@6Kb"++ܳ\&|+MI$4Y@Tµi="TNWVd/1Q(ޓtTdtQܱh|Grٶ5E_2jվV}\jhƹB-Ď )ӡdz{ҎhU^s3N3sUϊW!;/]]:ǮPYǃ _pLIn߆/n]_p?Сʙbc[!aW*пQ= +e))3ykY{K`o]nd+m>zg["~bWWvdTTc{N/:4VfFKa:lrœ=DU̼̒Or8d(g~#">m-aikO{3DVU\TדLY8K|*+rJ0c,ɵbK2jYvr +dqծ{Ÿ^2mq#C㾲ȇ]&l1|{ɾl + Z??LUݎo }~ϗ%O>RiUͧ&|Xd,1SwUloh˝)G^y,Y7:/";]7ݧrp`#?S[/s{ /t iv6~-8}AQ'˚HO}UGB$/ne<=tUƻ#. :_IZkkNm=ŻM1ȇhg2 7.w}w~uSז꙽^Ƚ_X SRJRZT-C>;ZL}owl߉j'/UqLwWMf{^us__MkuOtBY.JW3:_^qƄe+|=ɟKOeV%Fk^G'k[~ \⣚j6q vޔgsd9$?G)%"-q]V}Vj=Os|IQUǾ}Tu9źec ٘7o5zy w-xpE-tMr7r3+Ӊx1ٗ]g6xKKkX- i}`伣Zm%?}ϸ2}Lm01;)Qڇr. :<<8ABm;Op+ R)'D阝̙#غE\Dچd4,{ZEݠ`3/%5h_X +ٺsj{~kf~E0pxβR^"sT84\xZwK@r[ooW;G(~士{2:gM|}m쇵+؝I.v=kt=YXw wّcv-c>p\hf眷L)jꆼh{EI_۵MpƘ>'hC'G=j5]0o%%I%fzk,f*8]ޓZ,8dqkٺδB.WP zDSm^V~ Һ 9 w?7^CyK҃5"Sr~YPfl4V:Nkz}ÜG7?!"qKX/SYXv"F+IrrnYNjkIލe-Bd\8_hbb{0cÎ.k칱+Fwnuߔgh󝕛MXoߟܘdCynuyL@w}XsE[2|Ӛeu7s&k8IJOQ):ez9pv[[t7ة5uU}y.m8~/瘯?vUjE~ϭꙨ +U[ZT8@[զ\]'T?-|#|,]}2#$z9BϔN̹3G6\]N^W4c-\QUdUv`v|wf|kR%̷gwyz/f7,-xhgWkI suYy,z5|(_W*3dΙk^;"uWgDj%IաܲwI9xjҼK:oM~SOS7V}RV]ה͎Rj|Wx;a*e*ܛbfrb9_%Nr36q۟kڙ'WJ}e^Y!I<LV~ݐw;"<_'xᖍ3Zl*&żRsPN\!hM5>ZL9-J1ʮبY4LnXPcZLʶwz[[37\yiLU״>7Aωs\5.ؗ6%ٚ% <|owRaZە?-ʾ nL ?~L& +1g=QZqS;]>5PXZ1On~P9'N lzlDrynIXc3m%|o[x\++oP8?"ҙ)待NۜX`=G#'ΊWz>c٦o7fXcn,o*lX>3F֏G 2y~ldwS7M ;㤠+;\a ji37[~`{ǸYqa}).^RuE'i0WR@zsmvg{Nw3˻=*Zj`Ҵ'A/73H?c } +,ٞPؒpqoT{Qf}؛zUc(睊 >y0?kIaBK\jm88>1i¬~e 9{.xyݳ6!0+D.,#Z*٭}o2h +|"+j'wn?#Krl}uVH15;HJJ74LͶ!!s#I,3wiFFǾgN›4G-kMo:#3'&)j/L}K]*^}( z=J_w?a\N\lO;^?RIU|׷ꎠM{MW5ζiu3 =lɮ|ff;]g]y59ۖYYXSrI:i^uk_+X.@+qӢ=zQ?|S=_6[%Jg-3Wg\㴥;(PQ]/'Ϲ>yKj:6[|ƫfSJԔ-1W~o,f:/k'Y~|aU>N^q}Ey|s(_:ޯ],{sÅ@S}/˜Ϫ0xS^ZgoW[R;d_>K\qmOBO.~gw+e+v-L9uAbM&|UWiymߘ2QrrH[[P'Y_G[6`pV0wKAoxfS"bf3)R\sjS Yj'1%YnW?}&7sw{Md#gOVp}oߨ%a$ޤ,]D׬=qTIw[<]N‘s{l~8g_^Y:-nʞ?uH;Ȫϵ +7T=7K +Ә7[Vnbʸ(+(kjHa΂m+Mt%QQ3z69~sԄ7}lei%'[o?Y(V@JZ˿Aɇ%WE>ڻP- ?#܅AOig(NX0;Mlrn\+K;Nd=}*xn]{3W>{zc|ew=ę<ԼΫ5P#i⯛,SsvpԱc8z/`?]Z9zi>g9?"oC+{ ϓ{-/Xl=-*Tqy[jK|wV[%E$:Ve|r&;T_?c +W^>߉F+7v~d_]~kjllaSzOJ`W7>ɻ{w%">ˋ=]2:c M +?{cԄ(>"?]"BwJ;LT.0Tk|[Sњ+{|җҴ=˟9POK5 +bL4CbwAɁkZc3}ca>!Ef}|G1uS>u6s~QaֺVNu^Hͧv,ch($x5gDmܴ?;/Iή{,^Deµ!gܫ XovigdxV]l<|~]hT&60iꞛKMX]R1|6}kG]z&h3>^e^T7k.{Κwd>psb]WONS(R~qn#?WM{Tkr3K/j4=\g~h E+LrUkt>֕x:w?o9ZH Yܾt`_-⤞֏Z[OeWA/mfM߃V.zP>mj\DÇ7:۽kjI26?\xq?ôCّ }B)uWzI;;qîM;> =%)y70߼+sa;,~>c +\'mHeV_|:CxnUӳ}|U=Abǃ;lmOU[IjQxmZw|Te/gbɊ8mW[mU&% W}ı2jB'*tʯaU O>wmvsTT^xe}:)GGgRV*kο+d6ŋԱg? ӊݷ=YJZ{VI^F`E\\1G\:S?LF357qqei?1abLd58;cOKOX_̈sݼ ~%j>}24tI$@_K:nyҕ~i]Iњ=Q4i]=' [Nxqڥ,w{ָEjM'-se_:ƑM-C\ `}\]X&Ӝ_L9s콌2zK(-|0R}Mjvvؽ_$hMYLnT]+~xCE8M/7|ꎼH^[=|zk%Bkk+G_7+avUYd(7YQS厕[Sn +Yu\8O1 zUx~Kko}WɖQ5=mIiuk F-PܐS/hXµd.NI W?`{]_N:qw}3_T}P]vAˠvIEÍ$?>yۅ:S>_~[.V'>p{Ee.I%92O~j>].eٝwr%p3IՇH}9V7|Ne={8Qe˭so?utG6ooʄ ՜zϲN8DJ?R;w8Ԁ7mo}@5; { /ŝ-{_`8o  +(6MĘ˦U\\sFaiJ\ڷ`4{Rn:sߕǂ" +~i?7;fWa Ǔt?M+:m>ߏn81qAKwƫߧ͸wn[ME!{nQ)5ݷ{_O_/?y{d|L~J*mE;Jpd`yX9IzoVYncsؼOǧNW{,{:_Y7Oق]o/t߾G,Gl3k W)ʠsoKL9tʴ[U>aYI믄m}Lqx{Tu]ߐ(ﭖ'x_:?g`3ՅeJV<}q۽6$J2/UZ'[St _yMZE7ռҷ11[7h%/7Q*ZbYQX_#n d/g~FYsO}2 zۮyɬ[c:&8\n-+sCNJTV~óז7\f8|fVpĄYkjMS+rNKBVs{,bKf:l;-.'},֟|.sC4iIˢ' }ǣT#:): H){J;e6˵-o.Z2egХ[M&Le=ܸ%-`+/-a5!<.|>0mtM<ڻT*G_z]Sn0`ZvGӏۖ\ggdp{ճM +C8UZ_KQ+fq%b7gNqKѪבB3|Uj Hޡ}]KDkyW]{מֱk!~^^2%[ۦo>X{ɿ7\ٹ23h:tSW:0S%?RU\gwF3niGzͼ3v2ԖfgJ!ٟg*t{ MV50#~'N>UR+nsxXyͣn R-/gBp3_z\Aǝ.}`e䟴ɑq5wģoY!&}[TWݸ2cɇ &9-ko9~ޖSK,IWsrm{#OA!Yu Y۾`۞dwvU近qxUgO++MW/anXQއj ̹%*G?bEKOIviZ>T g9dtcBRIJdj6$)[? 1N}۽9ݛ\fyrhۭ'7H}m``%dc$M2/pן'/~Gw@ 3 9%R2D䞺wi۹mlKxuuKsT\x(sasnbbjxf˟oo\pF#^:קz_LWv6Lxk-|PS:lT{IEkqňk*MOW^GPDoyb8\9aVō)f7?폚Pr¢OEUɘ˩okܹg꭮7Gs_5>{#+LpKwuP&[yI];#r[}Z.&|ҺBü/[Ƭ7{g e8GD]l>mNJȴ ϞG6m:aHM-i}Z6i|O$ez67ϵyQ*)r +ytFdC&.Mb޾uk-Es9R%6cPĵҘZ 8]$~d':V7>zONel=8'(QxD]gvLsyi T7?P@ک_I9f@B噩W *md~\ꗣԄ\u\rO +lP_d#oOMV-;}ܾݹmА5߾q&=o)K1{$]A{BfK򏘬5΁KQv<]ߢL]w\ެ^vc絕ޤ$ްTEՈ 1.~\5cHfk{JCB3K/nb>"wH G&r{Og80?(H-'x?m'֟hHz{Oݮ3!7rCosr[`eR+Wѯ_4aS/9VGݾqB$Ɂ= nJs1t|ї??׷Su;k 5F'.Еm~™Ay'emwnsͶ{"wNu_"ۯW}BwzMoɥs5uֿ|z0wדW9d7jȶ^| -FD qf"1 f{\nXwG(&wa^ke`dzxϴgS~֦Nb Er=Zn/9 +dw5G&q|q5|q~ښ/松p9ǩZ/i)evr\~?ǑMëS*B?~و6?+ȿcxeVF^cj [""W)/ +9!5SmN{)$6M>MY\XXV6vmzP͛;>wHvTH:R=r-r +\!sŒ9oD3:W"w.OMN|em>y/|vMh *moJ1qjVVs5+dֲ'ԙoH!nɩd6%3B$k]nSW*"SNϚNV^^QvʅC9TxEت=ʲ?^7q/?;Ǭ5Lsc +7?ΫWjq#g;Xyn|dsntK_4=tf?top3S_|X5="ΫJ=-*j ӾL]UHwݴ7-96F>;㬓rʽoiz]Y1%R'R+uĸ]?V _NuTPiWMˤGj3-%25᪅NPŸ.^:UtrX9)VO}5;Foډ'|Qظ]9V;]S%õ7EYٍKNZ]7Msټ™J\?6SIÇ3s,, q "W#a>nnQNJZ,x-e]asM>>RµNu^篧~V{,&iśFⰝ[a\rc/ƨ]`|.X+-ӊy[_z7ڿ{X|tcbXj}-眲AZSsg~s&Gr7|x|=\\#V']?e3kl~FKe7|׋#4uoQ/{_?Ӓyߋ_3toKs=q~3k~^y:ƃK72#sC^yru^ӛ>'g]B0BGk7/Vy\a ƤҲ\38_=lYz6"ѕl  +;5uߍ%} s>m+~W)?ꐼcn͗~hћx'gZ{EEѯf2p ݠ&K,mfT_m/ËsrdaѼOD.85L  oӫj~4TTٳA[ Uo᱙d:%AFRJ5Rk'o]S`໗⍟|6Y} +RÌ$p Z⾔9UjŬw2'-^e ڻl,cTs͝rkuEtfbo6o;]s]/KdZ7A`:ǫ/]YoTU_e]t^(n+wػd}3VtI]={&=Ćebo9*дa=%sZ_wMlˋvOb?WZK?;蕷x//}h^x/S/c^%4ꙸϧO##{b"BOίwϗ:k<ېl;ḿ!<}m#*l:*}e3L.Wd% q%F=/Kܵ)]'HV[*!^h +Y~_f۾MmA!;5m&wj ɩ \j"wkNӏO?2̵y^g3='?<l˗ ׾pIQB^}iu]׿&%3[>Z+5%R+Ƙ}ږMqFvg'WۺhkCpҿG jY"g*w4~+ぽ?<ءO+,dAk.)Z, q;ΎU~kߏoC"[جJ[;ɯuº厜5Mu_|$oT^9fn7Uz>[-gΕo4-~.W}V(,_[OuDze͛G#XgMXry>#㞇]oɽ֜ _7T)۹^h䭹b;&ο7Y,Tc0ݺ7r.I.sVώn3M|nc=1սEAuM8zy}7 ^v$znr)ź]m`Ә8{&QM/yW +,ʫ""'J]̮5XyDΝk"w\tC(MXǫ}.ҽq䊵~q_O|^6ǓKn|Ytw=W<2Vi[0[e<9xqPC;$g79oQyf7,DP嬠wn֮gZS|]n iһr6^Ċu +IoLuWOǞ4w(ʿD`Ж8潇.Ԑ:s׵gؙ{w5#6wUfz:yu˞O<сC qoÚ>..cƹ6gLkS̻N՜go眘AU+&1)dZnXi9.%eT ,.3or]Ij}tzRVs/[X.HdEλ_C'KҮȼ6<[kX<-I+fu M7_ո[Iמ6){m˰K%osfN\{/65M\Uf''3[dyWrE^kv{ 5 dqYYr{y͵v'g;}^= כntƤR+xn??WZjğafn0ߤ?wyF?Xwi)-.=MR +T\ eҍ˗م/r>{^(s {Wc}?eϜb{nۥ1\s&,'y!HSou7UlndYw5't0 [ղMKI<|iԳ +ٳE=sXZcN{Ϝbޙߥ*,E~t/F=NTct(3m3䔾I{-c5o~>ubי;:87yyct-*K8x؋6é!9֍dw`)ZcssMns~8K1aۛ+-[%q^zZuSlnVF$/9OGIn ;$fdZgEY֯m}C}4׽gbJ6L0l]WM&_ _><+_dFֹy_1a_YίWSvI "8j[\਺mO[Bys溜z!f3nq}N_:&J6Ջ1EgRyӖ71ֲ-r%Xw,~CǼ|Vo=CR*Z_-3Gi??L׼kgg;^Rh]ե&+yQu[*3z_vI- +ʕ-9og*pq奮}^%q}W˗GL;ӻƭsWOY2}2oN}Y t5~wzf3WS} ::'NKZzŜ7XWW2gR2ޕO7z/u5-s5w_&Zqܔ 5u3Ա0:6VM&76Cmw[?Km̻jD+o,'K}\ioyjSXu“f\E +*]JE|͖O*y[Ɓ?zof2l;%Vro1o-w*[97U>L G?'nlϛ7]g+)=BTzmp7R96n[!ZׯPe{N65$R#94G )9Xtdߓju )/n-9r%o]dLINfy!5GElXtMG̥'?-Y|Kq¾,{|]eNӷ?#*t227;֙.Ư,+{ޤ9 [-4l$֪ycBQɅW6?'}E['no;)WxJn/=jOguOK7Hݱfi?& +!\DžeJ[ny9{W<.?wFW 7ϬM7)A1` rW,?Yy !޿Z;iMjtW;fqaJ̚oq=9@jgY=[-7iԉsG~ӄOg VӬ[40R4W 1"LlOY.־Ȳmj@k٦>si쉵`Yxu1~y'~PF~aB LXo{3OR~pm[J1?9~ϴҫV;vWX-,UCgc¶{'o +˖[NOb|?st 3s/={kAÑ*$L[绗 1jzDs蹇 +ϭo$)x<{+>wϑ{'0RYYlzˮ|ڟܖ r_lw +ε#:)km].ww/z)ZܫB{bVBhaJ=|zpÔKdY_Z~j]A͔7NJ2]"tfź[7qo~-{0"=?~ߖhwq„/9I) +=Ν'g)0rWjeztn9&yx)I'&MXu轓>>X>9<Twu[,lvvߊgp#;k}Dy.sl{Vm|o?<! }gXy?q +5.Leާ o +6U 'vsO[W+xfw/}μk>گOG%/ IOJWȟ܋?xɂe\К~33ޡGNr G3g{_k,WJ79=gu%*Pݍ[ ]^9]ZFm߆[׬hhٙdLf\CЍSĄJ[]sᄏf*VwSƬ}6=\lDVwsص士ͫYBh-ey}ЋJkoPYӴiW&On'绰٥{&:*YKiN>[V_H5fl?2_7dZXoԘU$szgn֙dOLq`N&^LU5y29k}^sN"xUmp|7'lLl_wj,u>:6ՄwY/R\y7/_@Q{K +Q:&mC^]lxt@CsfEOoOəFU9_\Z]H8!@>sWuOY?kJΒM`@wZCJEоX]6][m7>*O\|ba߬ ï+e҆:.\yg?snRs+ayA 16=Jfv}Q5r +^y^7wɬzn=J]޼ԊU.QSy}PW_}ԃVםmd',s3YXHYurE{{ז:pz+W!ڐzAcxe힚Fᯞ>)Z`:rGnT}'njZ1=yʔݝ}*Ӣ-:wޗyO$c + |vğ'Mw/&-kck{9n_+ΙCd~d9&chHW鰽Szj>1[=`]aX7go|S5m7ޚ~1x^vԫJgȖOc<2O|ʸ#?D8nH]z5:Z޾5YJ\pz-Gm+% UM[k>?]|]OWsc=]c~ΉONP_V]M㕞Y_$̔h"nۜ0EKWY =/zPbpѷr9+~u=%n.iA\Hwo6-Λym%KwV9O9-{`i +f̈O[΅)g }*x}x_f[;yk{~M?=[6 e g*IL;tz#Vw$[ؠy:Lno&ΊOWɸ񠾋Ӥ+n 7gwg[3 utX@O6,'']Kzï |S[緅~hzHO? 3ݚsxCS{>X{be[h/TT)~/vYJDg;rN 1%7 5ZsCkcz//ZGKC歱mٖ5J\հeb儉.[ox_[l쥦feΞ(=zNLN`tq]ەեセnaDb?[eyG⩵/;1=>tUO^ʉs5r\+ɽ zzV=mwTrb[jDnMbkL=w\X~j^ߝ'p%>kDz +]\ђOpPyg+ُ_+xv$C99gMWG¤MS3:8wE͐y &}>xϪc#d{iJT߱<s_LUM1e~uâ<+7qD +8>~\+忸Ω?>p7#C#ؼ 5zK^ِR/IBgev[tUgŞĪO'{RnM|/6Yc{E2doޛMe}洇n,=Ǡi>wmZ~@q+CDtf}n*}Pƍ[h\̴%vy-s'o򜕖_Įr\Kol5I`ݻMk/xb{UJB9 *ϖ=g;]o4jls/\=0rWɼjeVJŚ6.鱓shgZ[lZ޻n= 8Tǚi+*|U{uѡ="ma>3mŎ[[Fm/N,8y4y{/s,i[JNf=/^\ڻvwv^aO]n5wWs,y5_nITO[^9+ca龱]WƫN o?U[ٹCQைcV3v+GÕ79+'o\sjr^|䗺̃d̵w}ߔ+*|%f9*7씍 6%?Ôyš:wtKzcL9zRsؽ2 fsg%R+_^:Uj[o[ ]{eyԵyojR%9טN=A0 x#]:ks +Y׷]8Qvf\cEɫORŌo.L jsʼjɎs'0Rfիڿ4Ư]98vhI'w(d_:Hx. +櫭x&k߶6Թ;M6M˰W8VkXyϾ/yyݲX95\-dX'l! 'In[S|Y(UVpP]0; 5wy㗒.[j 'L畯NV_yH{Om>?OֿĴU'{Tk,h]pY XSDqzT=o_q|{ ڞu\f~5bTtEYTc橚|'pǞ] *5[gծHtfi]7?Rd|^}%W ˧J8l kidKT6Ǿ3Z mq;{?~|X/~\KZq>s6{ڼ<-m`~%EYV[߼?SȠ;EsBK<8gf5(3e\vi+<[Д~֕{z*RZ4{tlORm-]r.{UoX^zI`6Ӳoo.;i<(cϼ&htxTB|k/2<l~{UÞr]+Y3+Ye-u< /P3k ?YS4v/犝ϴЏkCO(72}Eq%f׿ntzvjq߷by?u-1A_ gV{_9wϯ2zpF툥*ϫq"N/)ssYd:׋6=b/]hʒ'Rfu>la*h5wU+r6zϞ\YXUyޭ0z'06' ?gVz OF}݉ZϽ5Νpkc+4u/CNh=sw&[Ճ}esD֟pmW/XCё>Us{J;'"/S\$}Z~Vm\Y6x:ȟfUoiryvJ+UHMgr3'Xv\}+ +Xl +wQw[ |o\OܩV0 rM-ꇕIr_p-yI|E{޿oUeBN )D8ǫӘל4癏o[{))([lYl} MS1僡~5V䩦+Nq"[ 8WS{!%լ=+fn-Y'geM6-(s,k3㿃{"30:駅VOs䋋WJڤ[^—"oo[7\J "i/f84mGwTųʚWamgH_-=B^qi3un?۲rV_~4.9hwiZ2ޔiG"IITVQy̟8t$h*MֳbxCA]?}0:JW!n5EGÌ23NNsvꉰhӶ DO\Yqzw9+EkQYD,dj…W +,8"}]9^-*7 \ +z™W6 _w.VU38g0гs~m[=JFnoY)ɶZcxgZTew^Rxun(jrKЛܛ\YyAgیֹٳ-4⾾Pu+EZj<խ8qvׁBw*^-n<(TR΀&>xC-jm>yFE +1=1޶~5ON^(+35yUf&[HtXNC!%>߹k.5ͺ^[&4VkN7+I|{яkS1tviF~4jX^(/δU|ʽ N^),򲻗Sf8u_4q{^h?i(N Թ+4Mc*3r&6FMrW?g;nG1U-zViz`&gpl\ cʝ_M^|)\'뾻|e<..w+e_njK\x91?6NoTi:Xڞ#׳Sϲ n4n L1 +̽osqyϽH4ol5^`P{/},tlINe–) aP"0+C;QYn깾PYh"Ki_~v% I)aˢi%y*b<ᖯ)G7o1hYnK*3Xug=]*Mi}5[c] m^ǹ]͒RаMi& /<*U4h|矝H?oڧu}L][~ԫ-Ô;z]Ҥyķv s?zݦ^s$>Skxz ŲnP+״#O?w^lUet9c9E.] K yoznimoo{diSֺٳdBz.?O*Mn^侦:e>9>ܱ^o纠&jGgrU|uKr +[7zQ}02+pҋ+}n>ϣgm2:oSjlz֞7bs7mա s/_s˜; +s?pk|As:<# +x$&KfdvɸK=5ܖֳN?Pw 3M לRz;m ԽUڵA-+[mc꟧(ѽTAEZq }!eVnxb71&u5/5ԍ7WRQfn'm^x`ZnS+=`v{+C;p5?Cf͛oC= +M}Db>nL|V3wMvM~|KӒ|YXOtWӻq˅GNĮ/"w|Q1#"ncuGIݗYԟeQL3gl2qϹ]#O\XՕN{]+ަwZn׮m,=㬵3g^vg(uݱdHz-\zJ{}*'^o}nGNΆ濧׹t.BKhQWh%큶>zQdO8U<չbf\xynA'^F)?zgC+De&ryē+?;gk6o fN'7H3& FXĒCYi3ܻ\ ֢g員t\>x^lՅrܔWarop_ΰ:G%~.I%{۲\-(ho!}Oմsg[A=3d<]+bzm>-TVIK] +/&ڿnrr,~<"zrb޸^|a}Xn_+ ͛d~J{g# mIZr6 {./bwvCXƟ(ϳK]5Yi׾?igKӅ=*-%.쉢A[َGx'sHԑ'j7gg?qM?--j1%Vז5}}vϳ Ǚok"1:J_6%9Q/\o'/9}_t{KH@A-Vϻ|o4BY +^ebU?oYqm`bTLD>*څE$J]%f˪_.xM ?$ULթSPjSTJN+ϫv+v+d??U?\Tԟ DZMJOTսS{9l"zYv[[+\~P6[F^?>b:]koiGv&˘y*_Y%OGs>6*J ~ay$qWI[+m&XɴB:_2l{Kb6'ݳO9DljZdcG RRM+Z?±]io7{`avo\@wwӢV;x?s|9Ky{dNi{~;/bw烦rV&U'3=[yg y[N[Ȋ nl1PyUb +{w7͊)k+VwM%̯v[Fnϐeɸ;&>2S;ֶکI>Yl1gUj￑'k6}α7KKϦ{PxZ ׌iIݽRށK| ًWX>KdksOLy1gՔyrB🇯x`}&[M3[Jmywm7ӱÔ[OWK BZLt0-qvw,/s~8okYĹ4!Tiwi={&Gf_Z16.F_kr/ˮOz}lt2gߍޚ%ӿGFFg'r2{!B؁G&޴ur*z%)fIcr +oyXW4Nԛ7aʽy N ?Ut/3^%`;]W:fis}sv{XiuԩUn7'ɨsj 8VFBA-6Z]6KfvLvN]v|wOyB&Şss-Cܥ+hkkPP|OP 98Nb>S/ Ktz(*:0gU{/I//+Њ2-gz}tr4s<?[n?o˪r(9ôW&z0rIOY`f!6n]/ +;,,w`ړ:OxZ`.{O]wmtI(/Z|b?A~MFMgvDtQUy(}ުڧl2P[c҃rz7OidYv>C>.m +5$:qcYgsMdͣgsa/n-~yz_rv'8ˢ)ZWf<\v8Ã7lwn({k&u/O`v(bzNOQ+G5;ߍ=zEbyQR"G^' 4X.W +SzׄG~r)Eu'6:}\FJw'jy`˪g<n:sO,o]OX +icbk3SW`v=b)]_!ОhI\ݟ珷Yi*mBjJno_Z#Y9}+ˌ^n[VˬYi3 墳l:Q[yC]P/[!6Kx/y6E%|0y 7. _p33n+9i:-.5PtɊyY)c[yw/<[7mOU=9楼\?mRS,lzgi<{̔qe^v}oe:%T[y2_OI}[M]i՟:g_NWZ߯-}yΗm9'e.[_]S׮fG2 6IUh%~.~2Epي['ϻ|=Y:jܳxvg'dϾyxsZE*8&XjlTU#Rwƺ(ܗ[o?Um0KSIO0W8Koْ&:=]B=,5k(7nh\h)S睢ٛy֥T,}/RItj/8Vr)k7Ybɨm56b7u,:g$ +p^m]Ub_K*S &4[~^{?|?4gUK1c"e',j5Z$Q$׾{3m5]pߟߚq>RG/M_Cl_}Id);u9 +l*oxq"#^|'zt'Za!-*4߿-h,_s{6yt1oF5fs[9{D1~:OgjB_=q{ ޅu]de8KI?pCZ2#Ypݎ-Yض{Vq}4{YE*w[%XGs{ƤKE8/ٸtR\JnX^YnI FTaSܴ|Owf^_+PdBmuˏ\:c5U-S5E<[6U*JNzWl9=f3>Lѻvۥ6Z|ӲL<ސҋV>~0c}a__y/2틸˃JiR'oOL*~QspU x6d{w<ĤD=icqSk[L3U]ܟ*1OX|x) R̶{|bb÷&kY5Wk:>{iͪ9z<̫W|.E I:;=џpV~Νw_*{wBJ /|Ӽ~UN|rk4߰B,cWX̿m9W1 k/>GoW|&ozsRRWw}rzdyo]}WQ_<اn5/7:í'gU`xv%bo֗\y3]?X=!$CSߋiN?'mڰkaLot|\)TsHIu+apP0?9+Sۛ+5E?n5w9R*tp]aePѳXClŢ_o_[Pw^WǵJW+הT7?;6')=#fbJ]˶?aE1 kR`B1 +M M7Ipx$^}ԤU,Y>s)ifg9g)=1,kb{F*%6iKۂ4OۯyT~4kΦ $giw8[g_AʯzaI?:˶l,:Vc°*EB }ݼ%};'z Z}PrS^E1/ 2g~$wagN,s(tvEb}#.-x=3ê)w7|>В0mƋx7)1#Oh,X]uy|KK>$W_U˺a_fJ7|m֓;T^xwGXca9]7DŽ.,Lw|љE}/Yib+Apq%>egˋYߴ+$l>HFesiMK.> /?,;hMxe_ +Tk:0z; 1hnV/km7aW?}I^eIU'徨i{ig2?:Wvo6GY<Sy.J8D]kʟ>͛wUXUu{w:eEٮ;rOeZ'6ۭSmk/9CnQ[gbP`s8՞<,vėLh܍SSrԮT=w㛚7]}sjz u8-Hґ|+k?k(dwb;%w[4U׬XLxV&;$?Y{h~bDW3C>+jL;!/m۩M[a~FMkVY{)vM~8{Iy. ۟ѥ+K/ZCh=Z'GBK::1meķLX潬Tsl&1}`YHwt6aaUbkspsi)z=u}V(L1iK)[fMkt?}=aE66i;[iԠ"v\9q8.ַmPlmLgྷ[1.@u_q-g--fLa\2q{m#U/Mڹ&K{_VG;fkQ?Lvu7ۓ16"y[%L-J*3C-a4WT %̿$֭:~ӱ33] ?x~B[ѯ{Og);=+Wg6䄩A6O~!</O͘cmIeXijuW+to|i9S[LˣsڷʕwU뿹ENۥ'6*=eB_o֥*/k}Ӓ>ߋRׯD'~{*~`ghMUF+-9®qWKOٻf +?5-RZ6e ^+ߗt{- ++FjN+&MtGD+iNI[J7Y[s|5Kh$ԭ?;D4u>g8uR +Y鵛olҼȡ[z鄞}j ̜ 83{NĪnRKޮzm/W'?5P0g] .{|WY=יx0e]]]ou NO2OL.>+?߹gġxd[)'$8]4#i\v|5̼=&;|[:;eumTn֊xAjS}v+">k|\\0Inrj 7no]e%vZ 悓.:WW]W^3Wj~\yhb<<7~{-6BGnH+Mc +2wZں,tٺk)Oj`k?+^e&uZm+7{nPVFCyߦs֯eU`13m%"GQOG1BZK-AfU~X*,)t4*WK;=k8<;[Q/b낆'rc5J(Ewr_wHs/{TUz_?+g_{#|EHqﱎmx(Yܠ(xI8fm]iH׏ZinUؾDŽςG'~cܐmɺkhCw<%'?&,6Y~*z"~@IcK]&MoviάX/l"xKּIRO{Z^ܚb-:sv7/yl'ز'm~^#%Bd hſ.HhŰqRZ7c +=X)nŚe{_7g!MdvȤ45݂:7S5v&moʳVmzo-p֝ +0o}ti̷{yʄFu>6;Xv{*c|kզue'IYqޟS?G΍ۅ|V6?;3Z(+[Z'~2-8WXUCw[:·>֬|aɶf:$b>ggw{lZC=cӁΈglaΑ2i諟8y_t[o̼5;aS8ex8`N} +ʳ==5͛6wO;kj5ZnV|ok;J|:D~% +7(#!q?u\ݳN>Y)_6ݧ N952 +׎ +K;03-{neڋ}:,Sw.oee<\&+hzlxi&fҗ-3)- }`֩E⻌_=)=]8群r YBpD~?䜽sJ*8?v`hOEEkZ*> n?F?&sYNoWHɇ)j/ܜѹoRQǛ5+2|?o֛/_y_vdӘOMD>X莳04ut%^?-t(JM|Xti3+Bs?o|4/f;~"N٥_w$ܘpyɡ?.'ſe7/N$-xQKA{}dwF`3/iw]vTɇlKSu_ l'1wZO֗Br$Me2|Ɣer-6v5'4njh+`z漵Al:DcΏ?~- M7?X4נ|9ׁ?[C|Gg5{ AKN:~Wq<0fɦsYgSV\ +矸oI7 }EV׼%G3S"M=%:ޅҝN†i6޶alߨ8nvWjoc²0;%](ş`xv0qOC)V'kCV[L- mn2u +]4 Bt%r|օp4FڲO}#n|$=P yYXXkg7aV[/| }+{M798Ћ[}mxQɵ Ȟ ŝ,NE\ҴMREveqtfKϑRoU;3|h 4GEظ+>gS81z7+uQnݜ⬼msǮlN桑Cse?ٞҭ|xdDqY"jۮ|q(HY{)cTX1o]x"sfV+Z},l^4bwV=Dg녥v%-}(+\nko- /2玐?>_|w{ WsdQkW*<sT>/`7s>dᙅ?۴Lԓa{M#R%{9MFO}-<]^⸧(w;fƪ2kn[X]o3rخ^Q(n$)3~hQy--7-~Ce]#&-}%k>O1-ܯK<ѱR\eSrr[Mt{MJ7V _;g38I\^7X4qG–!ny΃j{_fh92it[ fĖ-^!sPw/nVWd+Nu;;b#*"YT̓_.gZuU_cl! ? 3ZICs[{}9ƴa/Gr::|[MԹͼ=hl]^3udOr/r4ws4ĴT/ҽr s,}BDWsZcQG8ie4'B"HrE +K/S֘*vƈ.jyD)Kw\f;Vrn]a'O8vR)L۔rM.]p'`WuLyntc|+Iѽwcz:[_}y:+^}ynUpnr|BIvW]]{l8I݋Tv]G*Xp-KOKmOr|_vְlkSb=|.+ܘx;/3ENnb$tۤ >N߹HB3DŽow6psv٪Q7{}2J\(w D+֜?96[:)OܶbG'O2=ZĎO^Su}&qqmS|'fJ7瓒_zʼniWLo#] "/ e;zsRa^3ӺtN穖/LP9gmtG27is6"xU S'/9rT2Ӓ7SV]uQR]tO1=%r 7Y13']E^ yX|q\Odͦ-(;~ks|;ǹ_UϘrH9ߊkvL,fWɿ/=)9@c {z{W_>E?hl"p{qS ܱ[T߳Kb厓Y׍N!+z\ߺdTUΙVsGlN#sC3V%kW,dbƾ;S6k6W[ʼny,kgԗ%9?Y挛wTw)JݳQwM1.JkGy_:<3;vƆ2HZ2+wݵ.K羫śBf^&mtõA^g=뼂EY_Igo ewٙ}Š߻Тq+1u2HX{@,KNw'rgO}%0AcәxVܞ묘!:a ?,Mvus*)UtcՖ2 zz_ ס;ko]hW~^?Sʨ(uVqf.I=9'k$$Ϊl|U]w{G8X/eZ^>w '>^Cћh ].s9QXlIy쪏\:RVqӅW8,7T*>Ic.\Qt|'n.柖 +{fy^Ihx}̉V@_f6LfDz%JäRWV.dtYYG3tg׻+&79|(X㭿=i= VQ(x(Ǻe:s6]%ռ0|J3 Vwn,bO \hj}ZLr6¯Osɾas[wVl͞깴/e&9𔭨o&3ߪ\LfZug^(|ZdEs +ʋJct Ě3so(uixxT{8Ccgv7[5y1o?PX|<;a{ɵs$9{|VܸPj\n~m~|mشw!϶J4ɑ}^y< 'o6q| ḛ3xh_p7m9f[VϝUZ\ZoZ-<'UNy']xcJ͋w|nZ}g]p՞>&4?Ox*SB9{]0_7jR,ǏSgM,0cTWb<-7*_?Ǟ0Rr~[cCs;x]#ϸkWNڜb`4NN#6)ϻVh[s׷ɼ|`= h7G*j:V-u>ʬsN~sԭ,2_޾i&yQye"àzځ {ج6ko~%PO.UX%XީT|9v^k'{6sǻܽO&||`&5s͏sLynDKQ/r~Xp-l?w\{qF_9o|;oNl_ξ'rzgڿ\!ku_;{93S6NH{V5==L+SS|ZGg˯R4#wΕ\w>4kqSZd#!Y̋Gm軷YBѢ}_7cyapkg=oEadK9ۻB@~Vφu?.s,(@5Rt7F5>3~3t﫞lY"ZsvҪ"9X7NkyUF-A;+q]*sΌK%et qezg{h|'ﱸ&^2daiqhWE~{J$;߬O!V-c.V߹N$ւwukܞ$OWG̉ y{>$&qTE,62Kכjg}ɵyk6sK˦"wLG<=fc CA4!Ig;% Mz^N c< j,7QoH>羗!k|Ub1714­SĹT'vg:o(ǔ]Z{cߕ??9n 9'mG?1)7)HpkWvܕ{eSĒ+RtpdySHMg{rvҺl_h ᣖ.)+.G_ȲNݡ,7Jonzkgjl ?:; +BnGHh7ѺK )hs\:i\st1[83sϺtǞg}_&)rg̦wVVJ\s⑰O>u=V,OA␸֟Fse1-ΤmsZ?mw 76Bq&$Z5)W.`^enK_e'<6Ub 7}R\;澾~,hj?=<뗹OͰb^X .{:9~]-⓸"[ (?y, dpxkR̮7/v g+Fz滕brmE7_Wկd! ?wŤ3ᄍW8|{''ɼ~}5+$9v!GjC]ܶr+SĦ ^\`3#]eޓ])a^_/dc5%C}Gܭm6?y>[CKRWKX;a+˺Ev;.MٞIQg[ѧ^] g,H;c1jyGywb3W^~ѻuuB/Lpp!c酈S79zE=橉n.||+]{+{4o6u즐:g981 {I&[:SͿwEeږ7E=Yh-??$/yJ &+3ϻZrc^-;.֏oXͳ']"GgK}:S'=3j^uxOtлn=eA6sz9qIqE賆 +=eu2O'|ztMtC/Ytz/[O9/z9h޽ O[_*F῎toמ}f_0)žy2׋usx^1OG{V(, +}wD-$6!K'n!& 쓄 +~F_1Swf۞Sa]6?VX:j%+g7l ;e=*qwlKzא_\֬MzrJC]/{c$nO[sgޏ[JݡgjBk۶%ΦkOZ6\xA9{yL)5YߺZJnizύ)]8XrG"j)u?+}"ܧ{}{Qe{ djv 3LU[QΞ6mI,/Z`jc8GJU_xx/TmCTȩfʚ.yOJssnQn6?J}b'1}첝zo~Nkl,֫S~_8ayTm6{}?NZ?9V~gFplF]75%hY??VuLPzzyt=Nba-5*c[ˏq`n`-g޷zuKq]}W[7֑8%覸ڋg{ᰗ|sҢ[ٹxJ X_Iu57[Y'eC"W_|y[qTʲ3l_!z+=_Zve I% V.vi8VO7s:`B]ReD=]WߖbglL;-ih[bV3G&<w˂nHj(tyYͭgU ɴ1*v3WγuG{v TxNTQݗox'57ELōFg7N*&-Amb1 (_s反{I~o=t}JVwgf|} ]I;Ov xvvnWJ⮵_SZ*y6t-FbwNOz̹W/*>?vҼf3̖B/(^}qDC;}ꛔK:z'o'L~A׿vb򉿏Wy} *E Mksӓ+W}2.U>ӺueߐM7ܗz#CmfDL_̿1Qwv":;,ż-S7-Ju|,M2ߟ$RUyPٛn[1ksGF0g~RI`N +BHWߖt&;Kv])-wt +.ߩK嶜6qhbO+H~KNy`՟[='-lk{>W>a"l\--NoTwdp^ w:]]W`ǖL/OZd%kۉdʗ''d?Q-?0#S΍7yRjɟS49tu_EdQ]Zۿ%qO_Lp ޛRR>S:KrYFORO cSWLsؠ.57Qbgϩ_q?+W532h?Q+>{N豖 KV ]*A痢ޔhz!qjZz6^kɿ}Xz).{EM8[vbqY>|:y>yLٵ׮ 9WlQrϢ\{}f7>)~Wi_׮ZvZ Gqˎ)w4N㌾5z׻1[]s-{he C9>l`!rgJ[^w .+Z}U,ژa򚤲N~~F'mXjX%1Y1KƮ.ͯ2;.>ۅi7ޜ6iKWi5Z4ӟSz"0ϝs(;7G0tonIeO$k>P pՔњf+xEiCޏrq,̽߮'>W{% +iӗ-6u +p_iwY{ܫ:t~S K﬘T>ϛ_sWq\,j/Sc?MjZXz |l}r S_>76r1د/]Gb^y:m S~]'Y$]YX麣 ++;6*nVSt{-x̲YEs{7.UKt~xъdNSi)}r3|$cr$/^~qUڲyay:,2ZzpٜMCE\Onޯ_Siߌ937;P!Ǯ\OUsʱFPK$`q9њW*ߧҘsKUg>zj̿|ӕ5r3<>}u+L+a[udGudjoz w+擋jt^k0%'!;h Wсm;n>qx+`t$m~qS/^uvhmxJ]_{l 3뙙uI+.K'sŴxZvɜao)% *Kn:*iӣ 't]b㓺̹&Նs;+U|ȚQBj^Q]u)Ojo>R-Ooy/?^+ڋu/sT<`v3Oޛx3gfDݙ\~v7y31{yJksKBo)W9nG˥)ٯ MxN]Ogob +>w+ɽv{ſeua^ԙSNv;ia_œ״K,%wǧyS7}PJ=SZMf$ofL"yэ>wj[ߝ1g酇I2m/?8:R~һSa?hmoO /ق,yPG..D~ύr]"]#r>iM[)tk|#vƫuoxJɲ,gpI{-\9FmCӿ̍K;zyٛ)?1P}su ^*s.Xƞ5Xڿ}7 2-jͫllغߟ͟9`[뇻H?xam5+~}3ũnӾ~C&jUc`ZȆu f͚"s6>{6iŮɿ_q س}ԺiBX;5Ǭ{J+=6xxvm޼Ug)_(aoR>yK>,|Ud`l]&Moz|oDϺczRDEk,wf|(۲/wȲLc>}\o3fny3'zi>g6t.oNmzۦ\ޥqu#ݷ=ȫziA{O˳>;4;n6 rLכL1ea_v.,{b۹ݫz{]-_멧S X?6d{ﴴ],&}ֲ;_V\ui^/-KeUsul|tɡv/13ZU۾ĴKsxgnl _q0ۿ3:#$gEap~]*uֆvΚe<ضW?Pmobw>X{(ݳ}=V.(t@ri;N_J~tӟ7e5l' <cucI_/~p \rOLHMjGgHyT-%,8kطm.oعTnK Sz OwF"kܗo:=dZDrzlض|_nVUmwMb)_R+XzVq58Iwعs\Hp| Y]^6gㄣ]T-+w:϶._ ?\ g[Mr{ӗم_p+.ʛ;WS`}1g*֩(O[|kՕ aŅ.kXK_PwKrQks:ev{95m43zƗח|]aSatcko?dr,ԑHpuX9~z˭} |J\/3ĜZψe+i߿}cw՞qo/w˲CW={87|1^OT{.Zm:u3Vi_m1%48%o9ۉ2\3ܞ]fS=9'"v܉u2\^u| Wu.CBGş擪^=f;iYsW>d-rߔۭuK)kWG8X^ _i Ca鑗 F{m{>1S +j\b]݅bӢZ"1I;LK~AS+6WM5X#R)>[5k'>v˵ԣIksΕ_;Vt={eN?oX!"xY|3J{sHLȺmgqE{8mh,pVrԃeBðL:'Ϟgyaƨgu p8"?eOcֹM<|5E:3~r7 4p?a r*Zo|R]jǻK6>Q fS\=$ՕwqS3rK%uvqm܆tMA z_n8tIT{um>e"\̶3ֈWn|:^tL+o-rxnEa ~,W]>pQk2EY7laܜöVU_;7}p愈BQfԓ~&GyOw|=2w se ֝mW׾8ϛy1^ \=YҖ/l;+D/,6 _{7D]bmy<{)V+Xt*ΔqbzWNĂS;R8|֝b +Oʭu/.y4bK'8pYL5k|Bxl¾/\davu~ϛ%-)IɕuN+p,~ $c[{JgGYFMiQEr-;/[{]*u``)A-V )8YULW,٬#F&Ug}jgBOW׆?)x7b?B)k->۵e'8=tkϩX9%`+Me}wOT*W䕝pK2&ˮ[_fpٹ` sLu-<~+ ~AB%BV>Klhq\ *{X9?R'0ZU<ퟝacM~ݛ42!:eu;t7zy~NVPrm碥4d?3Hwy?8w߿}aϑ;%nqہ5Zk}Q,:Z3c@kk W>Vkab.U;L[=*+8eV +NYpύUK)ʇ*jRm_a*_7.wlW5)˟T\8}KEewvT|rAß٬ʡ]D +4MԽ]!a27RE=/X /+Ul8ougQCWmSe坮h7s{d˔gڞ*fJ>o2\ ;)g 'nl4HQe#兝v2 +bsCa,[.:Pog̣y [$>efK]~aWfYL|.(̨9~[6}fl0ߑlc K؟Bz:fj z<=H?KיYa/^:=[\6zޫ>aC:B\7yĥa^+gz{&* +svtnDs/j>䱾'jX7YWREit?G;'q!2Oâqy`#­+dkɻ\aGv7dëN~2no?d{{YsA#h0YLYZSX߅љ_jSя 9ﮋT;YcAEg Xeu,[:#Sb~5tm3d=\シ +_UiȪ%f L N7VlOgc;r;οݍώE,uam?'Hގ:a,I ?Z8Ǜ=,vNkk_"n;B8ybU{Y7/!M˯ϲW>Z@}. i~uIo!+xzBt㤟=V0D~y.#͖M*[*뽺EŅ+,گfd%kտ {H],96(vyAۏh>v1'xL(Rxb|K.nPWQطA#C4ی{lJ;d]{#m:'-ZqI݁d$Q1uSU'\yoVba5]xSk2e8v^eU۝7^zme[9KI"BFBf2 U}siZ?mO2 u?k{Md9L~U)uzBGٱ}n *Ҷ{7(^$ݑk[-EO>{ڜ#wZtiOIUש5kwT|~Ujy/,ޢE(Ͱiϼ9_XכEU门s6+mx/}5uNwfb ?מݯ>=\nUPgeZs"߻I:[넾\tp8c/?.F{ysQ:njSxT_\\y Ι>TUGւ}nٝV7{TN=o]y?笠uGSdcY< +|tĝ'V9rShp-xp#O՗K3IJ+󷣬%dT6pEc=~{t.o=y}{'=ϜJYR{^fz9{~ik~m4eև3lTՆ~eN/8.l]^N4NUMRRMGv焞Q3SO-g}AoU}v|#A)W]JO~^~v s9* Į9h`SwۢNC8VҶgod}qUݻKc^{xuA>F>%`Rr8ssYʠ3ML=#sڥg9l5_kȊ>oc3/ݒ{]er~Ow. K[c}[{t]ۜSPB2\591฼){M7I֟5Y/Ezk_b}`EСo5Vl<`owy\5~_nREWzf;-fj팿;OV9i"8H$ӫ;͟&R퓳LpO\~8gRLMe'<,w.wip80e g x荒N95d<3E=W~{xRf9 9.f y˕{tӂ_7T9'8ݴž~Z־NVˆ02}I/]_yY**eۂ;;YsӞ붧~u؞kybowj{od6񹝓y|E)ɫ[H{ S6>⨭Xgg{sj/H|N,Ϯx6˭ w;sf\Wii]T~z۵|HOrIU޲}iIvmKcN7j,(_z:?IHJ-j9öX3+/f^Jx]_rCu5Gjۮb[2IC?xqMi)WZsvmݵNlj(a<ߌ~7G% g.(q9}tZymޑ5ٓ&w]P2]n̻#sTyjO,Q]v߄I/Ew2EܶCWN;bia"pكgT^Zn01{du9S^+'v1$fcwZO=[A6oj24]}[&v;ǔ%^xNzf;,oN巳$j-vė}nRI-;2[X'.:O}{h{7,!9i>Oӣe+7H͑;o mj,adc֧%3WdK?uWyQ L^%鶬껢6y>9NchRmZy%MX귫o򊯕˿~mCԬ .;Sе4윑ѻ?xLP_}[=.wV*XG I<'-4VXl)3uzzϫ +~xE޷If2}otqSSZ@ಪ%4',ˎSVPu}t Sqh=x/>NW_tKI*pPNrKwuO:-j2جA3mlY솯y:ν=ϓmjr}˕:mҟr.sςcESt>4Ql5"gmbY{-v+/ٯ/~dpa^ע筜[5aVz  i6$zڷnBg6+bw*%2 6Le$=󺻃 +=R8 _n:M骐m UѬo-!|v]oQd]U$<Ö5si\k{Nm}3w2>5N H`ꖺg٧xN`-OWco~/X:ΰ|K9o}Ԣ~Xqۓۍ,%[ii[Orj-_LXޣ;uӞ(u2OZ:Gԟط)3UZ}WRgRj9 XVW7:Rgk<Ny"f fdL~~/N{V9]ܷ$mqGquݍ7~ɒWNs7*4m[ nbyڑ}ܳo:u̮ K;{[GmbjK}n7hXY]|aJHɋQ% ܐq3y΃ 'UY2RQ5bb wI9"۞XP}Ce~Ėw%]jy2nan{Q~" a;[Z>moP'K8uk7N;[eL[uU8Z07fe[no)-Õ͛"g6|8n|ٲ9^N(*[s 檊q1YUʏu-,?ϗ'^7Y:youAqt^&jRrO^99VisMqodXz+"HVvG6F?*2ޚZ QEg o/n[dSA׿JNؾJg;tMWv:95lֆUM<Ǘ&\hd?b7fx!u}@ɡ/ݩ[iqΥ=-{1}nRb_8ieVt%LjȚVk/_]iW7 +k9ݏI}ߞ/vV%k)=R{M +IvdsolzNoheM_z9SN!gh?~ЧO_yvlrRTYvHn!4ey[j57qy|MH]-\ZsOKD‡V<`<. +V~ +;u~Z[i?,\O۷pߋ_' &Nnbf~MsՏLvD7mfs/Nzfj0l(2. p4PY_ttWo4Jty#v2@'JƸiԷ5-wʦLjgUimپ3I̞#J&oWw<v̋"Gv/YrI:ʊ<y kkxdg_h'W?_ijy_ziI!2N?W5?7ZfEW\X1u _[qY<[vwvV q"菀}Woo7Psqܩ#g$|`G{o~0E#7/r0pA-Ӗ+?={˼4X9 G4'h3;?~.2MʫD;lTa a~aμhg硥^E/{VT~9&:  77Z!Rbi%60 tv!fygaR=>?r;D7f5k<>Wս1ŻNK!};eMw-NHif^_&5Ή|A~StwEt9,|{vE.bk+}cs(–zYH\D޾`6i:,յ3|ҦZsm%k=Zs䌕īN/z}EVgd<([>>zc긬Y3M%wC/H e?^LI8~p7|9W<$Ӓ{X/~S6P=s%YQ?֜+n䰜9yZ/"-;f+5u㷛E:n(:u + zܕ;_sKf 8ZtѨ*&-総O4~?]7列ꂫI GJJkni¼tݼ븪YQﹱYz\ ~|ؾ]=|뫓c>;|:sWDo g&ݖfp3?nK]k/~AFm~Ejn>a/Ŧ9y?ߺĢ]8WfICO{)!4_4T^ڕ+SF='ι5#WS_Yswsw5KYӲ[ҽNo[O)wY^}ΕE?*͟$)JbȉM:cv-z6DR놰؜Mo.9*\^=Nc36_{nBc]K?~رYdiY7<{>Wol3~[Ŭ~֙;m\E>w}^Ȗ]ڰ+h'X8k*j!?[[xݎ_*|j^ͲEKN|Xxw쬿Fߣ~1r*czT%N.MHԴ!߷޾[rXK+سC8Mpu}:Qe:N?v.}p@,2nݤ +5{U+.aWQ08w~"L]B/":L]?{[ʹj]uĄ]?s{C9ڶ zaRYȡlYk3wY<7ߦ1FiaۆNW]2/rL8d3W5iҏ#&M}b)[Tt{31+n߯6MƷ`;{޺x.ސ.-ђ:3Lc jObLyGy^qK{\56v4%Š#h7% ˙%{5ox|\-*fz)IlPqu]s OZ~f)²c3n:2g6ۗ9-4fEv|PYaͣV݅_u?ޕQxҪl g +7.I|=Iw߾ ~vjjEY5FY ;n8WrIGe򳧼Z}Nt/Ə%M6)aqIypz.[NEN]aw݉F?>7| jЏ?x֞>^~%愿WeOg57YO(Zdn=7'MXrMf=#=/ggn[}[-YR}ᐠw7ڷnBߋk{kf7 ?úk[X9_Exn _/>_=PڋsNlaՋg=tC֠[}K.Pj4N;6ZY音y_cXpfN[Qk>O}Qx\Bɜ+E<-$_oM~|O/mwiMv_:\eNr Inu=4v]!onK56iqbƽg{v>98NZ5Uw(p%>lsev-Ǘ8l`q|yՁ]!8n6׸۽b]j{wթ{};8vt!& +N8~t3Wam9T$o`d*2P!hb㩋=|֪s G⪯Mǵl7Y7qr +39v[IW'"9/#Ϭ0SD=ov6'~hcwYK%QRW,>?O(ŧ6|ya/?^U^9'tto}IC/6Ą4.౩wF4>yվWNt-\9dbw.HTᙟM[2A~gsY1Q8vRC+S؍/p3\SBr|F{v(d!cL׼zK[ynExhX O]b&77L,9thTXf=՗wLEWY@$9o/_bB+7-:v7vWNĔ]Bܾ|C= m-m?=_9nmYr$i›NmOp}Cbvu=nYnaJ^ذ升G"e?]nE2CGdͱug/gv8SP'S/jr˕:YW: U9/'^!jW9L ]&S ~ +.y0EH3sՙSqf^ NҲR{"aV̏:7+ Ws` sXyeGs$5aq "һX5IvեįqN=4@p{F_ut}c7~e{$,׳k_};%m}_,f}xxO͞MJM,5)}+UN0gunkrc({--ROɡ7UՂz?W/6s//z>OAC@#şWLWFhYJKS֊MI 7ȨTo9ޱź'PkW'X^]E7i_B}9׮QkM`?BL\ {ZϟXm%-A͛5C>_ua#7z_H^d!+/f_ż}Vnq]:oȄc۔{T? \ ɄDfϻ|?-qM$k5Sf菷r-\k8>?\Yi9fJ(1,U|tUgsN|>e1}[ɰ!R 㟋9M:Y;ky팖-j 8Yxn{"ZvlWVy 4~YudwMK['ĭʏ忺wJwJܧYuKnhֽ}fnttvlJGׇGmϮ +|2Is5ٰȱyGNWeM,viŹ?Θ;MO8_pʙ &oqt_,$o>ϝqalө7t}MPަ :ےJh74KBt{/ZBLqۦ"}ys\s~|3bSߴNz37K)`EZzoCIk Nz'MyyC`I)K@GqVÊuߧ_j;gE}T#-*ܤmeiՂj>owSQkNx9.Tcf\Y]sۇ7*Kxz4mqEUǾ߷z,ϔ٧%TY gqZӌK:Dfs\u+v.$&PGs9:[UF1yg|R +EE+t\ ;u:ѴNŧ +4X +5)e>eRnE杓~ȯiߟwEe;Qe#.l=k%.ݸ2᯵d{SoNmmf//61tZ OjC/;ݲr%K?0E{ljG%+u82iy{^oWrǗ~*ξ|fb(a ;sa>iZm'.z4sS偽A#Kޡ捵{Hm1wgS~z}?o#l>.tw[,W2o[U2NDA߆W^>KOY{VLoeVw\H{d[*(e-A/oްc'%~\wV=l,lZY1_xcoWD:#}8;k.0vpISsJ,EtWPkG͎!)-%f?oXo@[6K=K},x݁M1]/_#9wbɇO= 쩏l1ϏXLY򰊡ñ TENj^XeG%GW5F[\l*#ls"?L|a¼19nyc'KԥL>ni븦)m/ajr?~ix+]s˜?'^Q4rHٷCSI{Q3j- 6c2M&zw+1?P繮.M','PͻQn;o:խ|dڙY;LO1Z{jf!fw\yY¿ΐrn;W2' +]7T*=qMg + ަH_o2o6;owƟb;bʑ~j_kz_i7']4ᯈ.z ˲dKX_uodU{ [BED%U?,5/ @IV>+W֝,^7ՃQHNa`/& +>OGW;fNuawY~f>OP˛'Mx\p9o~Sp+U15EO9(,,w;ӻrr1b\6~oSu4Xs5`*) XP*T2n-`|_mܷK>+Rܬ'XB5K2/\Yt? wF|E ܖєTӳfͳx5߲nxQꇡdWbb{=w~[}Sәɕi- +l|yxۉ6X(kSټ,_cM&hp?M/uBHUӍgҥ,fxv=b$Ѳ8<x$ߎ +{]7J콼'im2{Ls3+Kk6lc>9Vg%߄ww/>5n \ٮ:/ٝqW: 'M̗zgť>2nKn(!zK?>+)M(59`wK }yK~ϻzf8/Y:{ڰ)^M'Gg=%:Iv?;r_6/{nɖoƼPokyEW JTfzR˓CJ)dl~ûl#fvm.<$=n'Ȇwd8wӛK7y~suVν+rd%[N-vT8`,a]z~W>Q];_9g~yB˒j1k]Xv3gEN6̊>̥'aųy^ +>ra{˜<?rXxqjo,e{ wd}/ WaT=eξ_ݯGK܎y%ȏN3ytK)0c_ː9{$::>`xǪϻb[kxȣ- c;:Nֲ~ηV󬮼;rޮ)Jz8'sZG~ 2Oxi:vWef}땩S L"ԍgi]%l(7Y{3..hʞ$k嵌;\]99%JxNƲ'޽2Gw|ׯCds6wak][>-yq}>2$CޞVu)X=:oxCkKOqܿipUkǂu|֏vp]xQ`/!䅴Ky/no*_.j kYoZ]&>|AxӓKw_j$&Ӻs_ŏ?/ջ0w2' ]kn/3L;zE>{ȕn2vQ%&|9z1skloVXxk#w-T?Dޝ-?w'-ZS-+/~?>nE{?,5VDa޴+J?|fό(U[={_-}8L}jÂzO68|hRaUe[hżV-.O/{_yx-,r$o42l;"kE~~Hg4[CnkV-, +^wyK9,vTLΌ|vn:i{+KZsW9zuוdx.8׷مǒqS} +6݊vak^^tv#e骻|uMm@hOC\{:DT=g5L۩*/1I}/N >^l/)۟ndzݳ-i+[uGKUT`|#ߝuoW|g~IBasĝ'0,xJH[׋׾ͻs})(QSu*r$[8չsvl{x35vZK}=Z^;Z\`!P5i}-=W3|`nDz|)lo?T=>fna>T&q]Mɳ_SDض}?ϗb˜Weo-c·979piJ:X6C`J[J+x[}Pp*DG*oc*.ߨ}BV5B\]:huLkKN* |PTZ"8(eOt/husV1[:>8Īq f6]iL)7Gj8V3YnO6gr~fszQ Z29^.c{9K'^ +V3ٽ֋o7]ûv?>r!'goTг'*U]}4E#ŽKΙ +S&UR??(mHv-w_UO#T)](VEm ' w?#"6kV-m*0Tk2Pk\{s_ꈹ5uv-4ulf;-س5`Nt:t%Ly1MQ&{{:>b >zSa=O&v^>bI nG{aQ1]o-h'ŗy?aHyWaKc{la;꫊%k?}%"5OY{yyÖS+>df +I4/`߼K7B{~[u|3"bNER>X5?۞s\1'a7)jM\ew_6\$|6Oqݬx\peC?bdw7<)f^-h-떫'[4sWyA3=LWw>Wgqfݸ}zQd?R.,Ў(dx> q-~>Iᕿ':}J_C*+Wg*vDfl_f9Xzv69ˢik^C炯ٓgIފ=+lٺ%zosqYnvmo|nnݶN*7|:SSk\ؗZ9SCU[;͜d'J69c9]ϧ=pVB+gzq|ax@$מbUyȑ}ί )W=ȽykřOeNS;j6+J^sjΥ7,[\μ2nCGlN8-}Ńg\N *9}C_0o?V['2#͡+>ݺ?_I6KҋJ`p7vGy^X}ͽ _7}?ۥE^>]0_ 79K V=XrSyiy%=\ۋ-zÃRʏޱS8m20caKn3qýiEn^_:oRnk+5f,OQ)ŋ _ %ߪO7kj枤h50Gѥ{{~oۑ*nN4md:R]E1eAY*]dWp^?:uҕܲJ|Scݱʉۧng %\|=3MML|v/3.1;-͟":`f~eb +C6=8-ԋ%&}ˍ5Vv>߽^ǯ0:to>/p_9a˫V"JR>pˈ_d{'b<N^mY)`1SYe>5ZwXU͜o"Ng6ɭLU8Qףtx/s ?0i-84Nj\x 핳ϡ??n;o״ =w)?N?yW9g]}5,֗&ăm,Zo﯒Y1\eՓ*WzgGcy=UyK ur{_-Ϭi⶷%]uΚ<_IR +U^n,EJ2zzy?G{6pƜHLfQit7*"S]V +/&_~uXMiS m9TXr^_M:#'y+]Q{鼛a[fHc~Ҧs{{ˍw*_#2XkٓeЛxY7|')͔շ_TUH)u?eg&Mn8ͯj|Vֿh72t^Vkz@`bj+fH`G-eԤޕ|9_Z:='Et/me2B%r2{m7^nqOvۻSnXQeZMGꛜ^|\`ѰE!ԍ?.;l֛Hr;żoMK«ޘ}݃}o}T'8:$ԶaۢMď])ȴtt)/^l޼/ym~.k}Ucqϵb}GKZln6]U.9CE޾[nӄA/O?=nnSfu-[-em'`~ywGׁoc}:`y<2Sm Ū 0vގQG,9?S7w0ݨrjZС['/p5^19?[?w˿j%jƯʏZLzLԸef;|q7CGlwmPrEuNdJt;䊓Ko Z)cSt7~haE;fy[Hl\Au~'02.OMN:tm7a3XO(=Qp][NL?()_`Y&ٚ繭OUS梙 'y-} + +Zs'gNν7NO:S#u[ikk^L_XI-\N⧭ߗif?L۹ֲLZe醷\{5֫"W6}Жn/{>#4+Cۭx) ؙqs KI}MXSkސOY|Yn1l_NNaq+GJ}3A3}kS3NT}3ۙ-ǑpTj;08or~ŝH5'fFzIo~]0QUN4z=N]yozd܀Y޷,{[|>GmaSKygo0C%LP=^ce'훾V^T{BQ7KM7|7:ir^ +ìT0(ȳ[f~u}w|71Y9ieۙ[zޘ7eՂV3ݽ_uSΞ6b %7M#;-p89X=X7>[Jv+LSX0o꽳чl=6cgw?ɝs]ŷz5g=sRCW+bl8Hӂ9rn۲6ˮɪ~:lԏ&?vuq{-N-& M]:$jL);zmU`5eS~ukMYU+a)! {x8wӏ۵׺73M"zGl%'Tqȋ*S5ZUuǪGIl./<3,׿/5ɦi5tͤGf;}qoϴ&;co=s,'6]~-1}=|΂~duRVwQgO{?N\q\J>?/魓o)*uBכ^piFDn>Fl>vץ-֮]+=SVl]znqo+ɺ}rS,T{7sU>M 3sAoa@փg3E +no`]tčK}\4Ğ32J/[׬ N~TG?|fzFfe +3ONrKwhOSރy!3]ž[55&/.Z{EJf.ElrVQ1%w*fyiѵ56sڤ4N-pNUo'{ğKOzhι A3LFL>NW]UYd5ǜWiI9V?oﯓɓ4|Jdνŗܰ!wǙNm6y.iw~K/{XSksjXRB7-''|X?/rHuoPmᖓuK r,ggqؑc{;;֛MQP{X|ɩ>ȫ|׭#YDN?wioqnϓ|X.8孾VW]m {Y^PIY}\=*Jt^pi*~p+-z=Buϔ7qRe;=-랷m-w?[bǮ7䒵%uӞNu VoELOEb-vxRi\1Oo2}wݑ3,D^'eA,|}ݼ[eٗt]?+8s5ˬRjxz~k͜ǿӃYSif<-^pynzd+{|"W{?EOrU)fO~rMZ +=K*04}B?= +Zv4ۿ`ϙQ\geS<Ԥ%O=S+䇊;x;|Ŵɜ [ϱ6:tD^@{qƕ_tJXbzJvK^6FN+NTUܹF [ezlVM~&g.xoRY֢U ['F]mjՏNԖǩD鴟 H￝.3ؗ爔}_c~{oGnY悮'gM;rDK}:y? J͗{*5l4/&Qa݄}?5hykVO_LtDV 6ywìw'k@N>XO۫/1XWemRs;yJi!,a}0/=^s&΍ka]It~~3zOV-=GIm5'YN(nkeڤֶVƝ7O)ΨV+ މlnmՈ]l[q̱]c.X86к.)- +#oMP\}kӗ6qb`͇I+uׂ.Wm?3/yo[eUUC5O]2s+֌ѷ&l*Պ:4?+Q9UVvxm t^=]U:QG{/X#ovQmCI |:&mJo8-ﯟ᰼P!_'&jyFjA[ZX".lꞩlzDn/Ϭ g&WpkoHчهطNg.)*K̜͢|߸_"ˊVucy맊ʊaiІWg)tw O;[bӋn՟.ޖ=VJŢrFK^4BM\.>їf,[@nD`*{mcv֛FN=Ri}MɉwOܵ%z(֚+u~RYۧ>ߞ3b}ɾv;W;9;LGҔgַ}e\#wv9_WoyloUrه[\z\nͧ|g&vnUmVLMtSjo۟s|$/[,3ad!ޅzliη7dߙOߝޫUL +1;9]) J{qmK4{uYv|&+$VeƓ5-Ց.V=lִZm=IXw/[dE '{jc\yT|ס4LkNȷӧ9&3sԒ i6kYƸ#ONu[%{VpWz)E6L-ߥ}mY9_rKor9;/6/\uFҟk7iW o]yM&Ǟ,nM]`'seg?m JL/x^jKU9z<#.Dׅ5hu+Ԓwfg'8B8 !>e&fx&£Q}BJZ1ǚݿ|.Ueۺ] cS +X{xq{4gνX~%F=J/mMRѽZ Mlr;pR_T,W/kp\q?[hs۾aݿ}w][[QAeǂz:]m?n}sG#~MZ.hg? k.5ݲ\fMڶ/f m)/޾RU="5@ЬG7Gq=-u/wO\Ům֏ *oWM>AAjb 3f/8ںAfourY5&*sŹ+e6}.i?"Y;iJ}NkV.I)h5M/ߟPӬ_ti1^>bk'6LXPC<پTSyH/ӻV9>$>+,u'&xޞ⮇ Jc1?%&ߏOQ 3jQ=BmǢ㊻dC,nN *ܖP$YE!އV:zpcܜ* L3~SB?0=IOݙx8\3Ӄg]U>=Q~)m\Sٹ7~-4NEG3*n>ݍ&?m+뱏3I&k%7g>cqe{-~Z*aj\O25-JaQW7cryGgr+ D>kΛF@:V{M_fj/}|J:ѓGx6+geju\V ber>UwM)"\ȶG G*P55-M/89m٣Vrw_6clLɏx&[ZJ/^g,z-g]Mn^שK^UwzhPR7kTmrչ9K,gڻ}Ȓecczy</;sTڱͬǓNKգx;/Hʷ-&tO1IKio}mg{6cP0݌.濹Cn.v{_>B'fךM~LpUbZcYӔauϦ9|KXDjqƿ-l x<}> ?Xgu;d<*)myU! 4`J*܅&(\:;M[ ;EOeg-x<#(>`LWŐ^ᾝgzM=[/Yk U2+[k=qwq\ˈj*=wUu[O'Oi08Ӽ⊕V +:nmTۛt22/[eeK w]vWU6˲{^m mrMtfnÙ2Fׯ{^*]XS iI)烇l$xyEZw_kqk%]b"׺nO͝*iW̿ke-޿>/ub Ʀܰ)I٫b٧Y[wל/;۾tT-Unl^5 > UtɡLhBX/ +:h^VǗnG_Kʩ54[ANʴB5g.w+ϯm>1uȴ|/EMq`@xSŠx]R'ܜ^sդiuͼ׍Gm9mXoVөt,t%g~Űk~|/q-ÓS=SLU?_iəoIͯrڝsbk?;WHSmZ> t?#Yjߤo =n]SCYWۘ9i%i7 6bV}gІW{\zs_ 7UWxy^/3w[K1zob—UѢP0ܫw|T7^"'CŇ+7a=}͗߷jKOE>sD'L|ciU~ߢ3m.iJY3(%X +1[қ>\pNmߠ%|drl÷U5uM9Xi*ԸY怗})wē/5k99]ywgÝ6Ew'}pܳQ,bƅXI:o/d5g=gg]Z[>"`OO,-|Zw#1uVlKG_gO_Q?ɣ?ڮ+xX7)M- loRaIs u$8R7%G%?h63Ǽ 7x׏ K*7H=PhVT?wfO~;f?1[{sW0EdfYm>sF8r5qYO}; SCyZDԃ'K^{{<\fMϒn_6'` e:+Uo]c=9Z75k9.Oط*oZUv&d ^ن2"u7xX6-iRaNR̜tfG[FmD02Ob=Ƿ]4vG==Bdz.%|Yb}9KYU7/-8}#w w4ߒ2Ϛ`0te^ʒuA[厤i[!lc>;,s\:3_"Ki4ojWZܾFm:9JH<ݶ+y9kuW02?5[ǷouUZEW~*V;P7-bKu NeK4-~Qe{e}%w*7;xN +=eP[s-eyPvl5Nax[dU[oGNCƻ;%7~"݆^Ou]gsL8A%}힍:'J[Ֆ} =5eeYyNK/Ij>3|'9$ug5ecʎ1r߶יM^=oӻ2Rq,ڞy,Y6:?m>ģ}FܓѿoTlXDUnWpY<&XhŖ/[3t8J^0忺58E|Hߴ1f/.:So{)|m\nW\׺ w.֯*?˒=,nu⟚քZ?F$eᄌo~WvrNW-%}xLUt.Wq|(ggvφx7l6*To\+$E=9밬 Mfeso4FoҙrwVr{#hPΉ!{M^k;%ot&Ht:n&޿gϢ՛-$)YiTyԯwx2ԵF,vto֦r>v},o>+XSbM N-lc~مSlt |J{wMZ-t^!8AX*= 3ӯ~igٔ\s K iɿGjYo;=ժo6/+6+5&L6w]CJ w.TK_I/جќbM[+t6+Ɖ)d<<1_0eQG.9fYѶɇ+.l&]^9cptcㆅn6b#/jkO<7鿝7ZOXFUk&t?4cޜǶqm9`4'(/ӓmUs;&rt/kŸ ,ftZ͓*_Voo-qUҌsk,qmwLJ~[6}r{#u?4*^iպ^z+gruq$W[owa_bhI_9矿'ɿ4u4kquQ*rByWx>uh[{>ahwKmWUp^u~/oR 3ؔ-7ovnbo5u^vjf^yǍ lzV_SϹ{V{7-2,P yKw6O|1&]aU?_M5-"Oqv }w 'r8&Q1ogǗrǎtxt)pz9|ۼ|muxei2N+G5yk̉y|̰JЏoΊ-^|!`Vrvc7|ɽG:%$YOAbq_{& LNzbשU$~Qb/n9MOtzӓ2o[ߑi}_ndtb<ŢJ3%y +}qۓ)&X/ۼд38ϧT=~]+f5o;"rԹ7T!Yh;lw2>"BgҚu4b*=ʹ)tKty+I\Xr+Xp+*]/OZ.n ?V?XsveE>Zل %}kk*[HC?g|>Cy2 rgN/+&yT7TVL' O&Hkegb_gy7ݗ7Nra5TSɬU}\O ^q╮6}[_|³J+~eH]y:nԑ| 5S_|G3fKFun詓5 |r4Kzy1^<&?w`wAӞ>(G9t֪~ZX`9E;6{/g[9m_aO\uL~,:uGV4-R2V`nL`vz/Fɢ$j(ǔ>^n% zT"V*[ot|Nn|uqe^]!*4wA1#g&~ϧ={b*B?\`{峰J3qڒӗ=P<7앆ַ?5^eʝi .۬]ilϞϋN[n <#K޵mu L\7g;޴-n.S~%gWͧoP-yMF6ߞ7-{y 9ý 0\jnmG[۰l>wvGt Zutm$a"{آ?Z{9VAKQLKU"毚T&t휧G➜z}kl:Q+YtMi_9W-eYm?ݻU$T&ZWJzߪ9a6h&ڻLũ6nE7SϛUdwG&EdމO幻zȟ}d?c񙥍3QraٞGsY g + J,oQط)`t˭ |;R,ST4!*,K\: {t3~䨞a+dC-\;&%?7՜&-]j W6Jns 7i.ѽ[v9LAʣ:^ϕ3^j۫##h1_SNcIL]Ɋ}QJ6{ք₶>%[8k-%7_:6di9{۷ apq o/iR۳.l^gCӚ%57*L/i}OR涟3mZqk|tX?*NytW&Z갌vkMǟU[-^`}tS7ʗNkZ ?~mf?J16 =YwC~2ږF=Gusl<˛W鑓o6\x8Wbp2X.{Lp\eΛfob5Ws?R+Ɔu OH19-t"VݴOUm?`VbB#lXE՟ה?!Gmzſ:L%JrOO9糑7W驎/*XDɥzWa! ѫ",Rձ漗uw޿5U`9bCm:|ogw*m&45Jq`E~CC9f_P}ogOэԛ;aAO7׳n vVϘXGXD}8, p6bnt^0.]*]kpW&o0?0e_]0Qt&lpY{*-f MI +P 3g]jWnyS\ugSo,vrڵF*Y?.W\Kbݕ: ɟoN0=}vLR4i%N2zl -v_S^ӏN:ƴٟWnUYi'/np^M4Rut;6H:Ac;F 'W|Pį[mq@-;Z-O ssqM׮ImuAq#<::%]D}Y[`۝;M7\ݓ]2~S3\'aH;[oO +G\'sΈ=rU{)ACj{Ztyk,.=Iu6ݹ5۾|e3Ul3:jsQC<..{뺡@=BSg=~u"8rH >Zk 2=Dp_kami+=:u9/YN% L۞Ux/swDz|VĥE?7銉渕G<:zmuwD֜qx}y_~5|!F9`JQő #Ϻ87úpJ{[g{.ᠳJj SGʴ}կ^?)qޙkkz|k^OX֑~Ns>㲣we3~i77Ԭ־t@|BKZo +Ü7&Tm:ڻ.ği gT +\?]q/o'|<Զw:Se흕[| ;4ʔ5Ʃ'-oڻS9]J4gѓJn]vX3+b"' +?~y\M9M=ǿZ߻wĥG̖fۿ^.>5W/(;Kצ2Ծz9#ِeY^$;LT)B4Pb-r$o"9_оYdxy KDS'.xۯzR춺L.rs?[|y;O.d/ug8`eÿWSs)ugȓU3oڽUy.oMiڭGN2WZ}&5W߯.xKG}8ۻrB ӛZ8PRSպ9d`yՋGr6פհp_Y40ޒ}g +|};\֓OqZXd˛ƀl9B<1[S۽(tugfGj +ͬut;lB~SL|43*9 OeXпiQ;.>KwWFFZ|i2oߐ.ǴAKR} Mt;2eWߋlɑUk:p;⥼B;RdGO:ô}$iWrL T5]/]NnLQYyuzk播{|s}S\b$)w`Hrsxƾ o9cw4mS&|1ik Tߜp -s=Ƚ-dw|>QUF~ks+τ_x2?6UCF.Y`K՚&>8Vpqhi> wܛ]m{"1IBg/4Gb]N +ZJRN7Q-Tqf2!3V>→K!V׮>HaZjOSۅ0WSS>RY[(`YO[RYoͦn^g.XlUF]OrFoV~=c1:h- sZ>}Q}CZ4o9peާoܿmc.0mr~jXOK[~{{z%շ_FXҰCQik#>j8gǦ⫚^vO1wjr\µ_:c5>箿+9sYKV cj`_pzׇڜr-{${  w?+(&^뮓[+n|'S2jktx/N8cqY~g}N0HpIy/#jW^ǿxƱGͫ-[KvKb2g(]rʿˢwԄcj w=cTr/tOlsMuop,}虔FNYϯY![fyowW*^j Ya=Muyb}/ *ڈHMc:55k{?/_0WGQDZhvAJå#9In2sVkD +AlB&S, ~u}8Rc_ʈe͞u^w`+&HlR{ oe29r +#g˜=P[W0q }ۣܙD8nwsѵK<&_d3W Sm kY uQ8w`5ex& [70+wj^Yg^ެ~;}%tTKw,<#7stcjlYW=Ujf)x<۲Ԛ*9i&VI%[=?ak$u3!'Q Y-+mP>x] Ym龚 Λj{Esozq#w_>PVߜylE,a+3]j}v6;3E'Xp˭:qs>-X7Zۡ",zm1pU~~cƓ@w[2ԅ|MnWnvcg#[+oӃ+GYf罏ED^2T-XЫ|g;=17kؔ-V?-}eRSR^ng2쫌rIrYWΞ ('qFJ}e'O}^%{[SvFR矻wM/}>̛EߞdhƗ 7_cv.lVU_j翓kΥߖ+oo9aO(fu{?oA%Oxb7PRXɾrzOyWx|;mJ|fԟJk%6\,V×U]E*':UQR4Ɵ5/Ԋᢲ\&]q+ZݤV6r1g7o6>_s_DžLk'}~ I*g1EU6?zKy&nC$]u|1V<~ivu dq_Y[2 ygLjWH%/J<44Vhx`gE]Y޽  .\"W:GlYT%=kOƧinWX%{` +֓3JSң[Fp ]oŒy=u\J,BۖK^yyo)c8 w?yQҬ'~Α(&t\$'_`v^É۬$'_ I f*sΤy(p7|rIfK}_ɝ߲&ƹmo쫙qⶉzVB5My_\#k Mw.?mY\%aiK:?>zIw[qLfl_WSD'ɶTwLr-;6]J>>EAhoڪrɢ%y=]Xl^ݣ%`[oPڞo7&, j,q`#y/%b_}Ӛ0)W=j:3uvH>Qat-taP;׾WNWe_z"׃eOl+gѐ*a 79tn3;l W\ѵ5| +CuL׽:{F{s_#iW*Tli?wG̘=%p%5nSx;I5}wኳ~mg$8fK{k"k?X {q#޳  ^7f;q6-km}9}GXiߧ/b<^*Wgur{r0sS?٢9idKmM}ĢwKx +ߘrWՙ.ׇSi+³V5'LiX+nj~ ̿t{VRx +jMdzjח5>X]T칳5#в;EL\&҄[g,k2_x9J)J ?MBfv#g{:)mcW{Sy]ۤf> +HTdqpi=M '.}Yܟ ٛ&xW8[ug&͹ofb.3/<\{*~x|{ıktS[|}/#]ՒNr[e.=qT 2X~={ku rE2a=G26 |OG.wd[nJ3vM:!2͜oB +&/t.(>#Zv]Bo61;E,/\PgHS-^e4a7M}6=NVw eDΉw'-= ,;y\(dqz߻.,>eŏح^s.wxӥ~p~4zWYEuבy2&&Hqܽ?bۗLa7l.05eĐ{>0f훦*G*][?cdJި)W.!>_鼩j\JۻX>^||W=~MvI}juOKNY=k\gmwΊ+Ϩ-,Xx՘zvx=W.-YˊO;_ܧfPk]qݾˋ\&Ʊo]j9vXHpn7׺e/1}Pp)X4sYN(Y w:O7CKq( o->]qn{6ۀ}U],%:5VW:}r: kT.}rXF׊O?YÓzJ7y{FvS#o=~}tY3VNrms·!&S[3VxuwN-gSB:N.\d^Y4;潓7s|rDGk# <&L=~WIU[d$n,tSggSfȟg[qa9kc[gMPcV-Vow6?z{ҷ&4,d-)<מ]Ugw~_5+sbw[K״Wp,dJr NC=i{Od|h ]g9E {`3;>M/ЋB\;tz}}^7(g595ʹ͹ڻ/;dzUjv^._6L;&yąUOȼ4ܜ& +7bgkۤbG52d2pԯ3ca f$-6~=/w=S~)(`ņǧ3ܵLMlɯ$y"]=)6J1ֳvg_pEeΥ[*N_y獜;ӝs%kld=m)VԤ+jt-XWuT^\9E嚿NɞX'>q=;>I}k'N|v޹{_r/~;J_r^;v8]st<%De%zf/>YdK+^[yKLgvᦅf˚=4)̉Ru]iK4GΟzIJJ(q_8;K}<,ҒjZ9A|JtWv5Mlg ;|>蹋p8(j|qڮ~9/ZRD1ˋ*zT}N}Ʃ6vRi۟+y7|3oyſ,3U$Xߘe"՗~۰JH;yM^>wk|#l{Jof}(uI?w_!ԬDjy2' #1t?*KV80& xt͸ƗUk7],@_Qߧ9:c ,)L=_GnMV [\[n(Jocl'OL#x5.mK +Td3 O%kקUO"0q~о̺z"YWg5xgZ}?E|o>W0U:#fɓ'muՂk?e/v6ϣ{l;哄vW,jK˨yM۞:9'U bOO׶,dsf߹$bփ,Ozc\=( Ɣ6g:8~v_[~i]UYj%^lo2 iguUzC7wf>yFӌ5?7v ǥ^zWv;i)S/ _d=b-_Rn(Ƃb?p{!ۉR jd+C.m/XpG>z}:SѲ[9\y8=cSfqn+3-fYE +]kC0*Yw\zr&gX+}Zu.]-_&nn9.a[NElݓ0qٓoTpcS_~Ws&NƔaVL$|)GoT5rԩ-k. [.?ӗC(h[U|-Ż:kފ} vsj/ +?zMa|~o8o.ຳyKWE[֮rvwkX^Oڑ+Tx@Km. ]\CIv-ӯ7GE_QQ :8WgK_/%<-ߨr.W6{ݘ_)s<$GUOS{?_SgGj=&K}jByʂo{Pk|Q"amˆ횆lG7kL^{ꏠM-o>DMGnHvjV:'嵟=}ZY‚/x0iyk\0?6Zʅ/㈩TɒWջ*rnδ|zgR2szyW5auR\esŧ.P͛-9<փ wܻ|c~ +qhIc;oIS +՞wS~c'(MW}y`nk(r-|p;ڬ5,k>nxw-?4۟ڋ}Y9//GOJٽ`ҹiW݋M{ 㑗IϧViw0zTmWLwDˏ\zlR|}uޅy,]d駦ɕ'{teWxe16clW{=*ߒ>^$U CФq͏glY>v'YW +<=ZQvgNˌn-]4ٹyAkzb7ܨy]"G5S~ɮy癁n]Ub/+{9OV՚F,OW^Z7Ǭ74p)@:1juFݞ5/SCUw4eZ\]%u{ +xN绱״Zoe3⶞cM̽> )n\>;N6=K={-_rgss2 8WΜΦ.߷-O5+cyoɺ޿e%{ڼW9v=tu|HPa5 3.l)Y藳ۘeo=t}?-͟n^TυMb6?93vavUj{֗wX>-0!}si~W5Us[wwnƔ5ܜ?_Z}eյ?r_=Xٖȝpu2C9Ft++=/XlrorRq_}^)s 'eVV7'X\ýV5KoSt%sC韩1yoӒXb˽b嶯}7Ti%ȴz֢? wmb]^eδsMy_[Z0R0{yeI]_ŧ.}ݖayמcgO[lxӯ#{e;L/N}84+:ܬ~{U³sW=;w478rٛF[lsd;sht~xvڨyaO ZT5 821!Tw^n֚_DtSfw{2ჽsmbbԔݱdZ^rqL[Kgz:LxUMgYzس(}i)ΘoCP2ni9GW+8;J%Wo/wAW7CͲ>7j+L\[)xsՙk=f1fܲ/eIg|5͚+GVޝ-Ow-[xm{lo1MVb|(*|<ζM޻ZX^lʏiZiEo$$M̾{n'ǛZYbnǶߚjR!l-o:U"%h%M^Zxض]s`rH×pvƜ5Z^ǫ%ت7x7X/=3Ѥ;.0T67Yko"cNYIwTkbQQT>l]ϝ5=J.5)[gG]]g,{+8ϻy#oY{[wֹWe *PtU614ww.zׄGZԘ~Wֺti5ZO>?oIy;5Jքؚ,ᄈڞ|KD/_ܥșZٗ7}u 5[¬4B]+,y-a<׫zF;yMyv\Jz(&~jM"_-#l YܜϚ5x2iƧMFF;ie"RX9g}ߩmT=檰vZzYQZ,yT})}%`?厖u,{ŔF̭1֡rGӴw/Y+0ќ跅]Mf[z]9HY=U._Zyg]rkʷɊ [_M ]^~NۿW-}zrĥ j6S4݋)=dkFSjS9g$O~g o{S'/xXktXBҵ+P*tVhQ̯KK&,V:Q[|P`ue=d;ق&pjKXUF`ʥŸ_:v~';{֛?^ 4VFp̉ *IKw=lR\ꝋ'"NVa]{z6䞐c&n17绫e㎈B' Ebcצ᎛oV`?8O:&L`^xOYj~wyV}ckv~Җ +uZrK|b%+'Ώ7yŻWuHݾ}w߷6)%f2[4[v[| }MY6-|yoX,>/G뺹ɳ3'eb֌t>єY-53ҋU4 2-6lwًy,XY3v'sGzUkꪞH'4jgs:A\#1bI_J~3Sڟ7MdGT Rx슔_SlWmh,KZz|+FiXviQ\mYsU>{>.S%ͯ{;i|bBSy^wq)]d +/m}n[zd9/VXr^8KdvMyg+l8i=ϻoGufU}5W|]O{D |[rG/N{TpJjWlk k[L13!28OC30`[;d7Lp"ؿH:?-&:GD 'gwxrc퓹n>][+'wsqF.)<شﻥo}<#ZWhŷ/Oa*=}=YM(iMo[`b'Wf߇EKv\t,\u3wNVGA󑺯 JW^ڽ4ƌvEJ%o ;T~?+"uǛb엯GeDv,4ސrɝӛwm}7&S/,{x!z>^_^k?5}R|!gS0OHh茐Wߕdߗ+~~Q]hvIxu>`v$]tfc. +lpM2?)*fWzMv35/n=Vuʙ#&&&/ |bdy4m +5~'q:Rj'OO푋߾&ׯz{gߏmB+e~D?/mw:Chgt.T|qֱ4@ވEbjOrq0oŊwMu=ڹz6ϴR-]j("t8'z:Vz.[uK8՞YƞXlK;||~c͕'18w'\@Moa74v=vaR9>xtLÅ'VrRuz|b4I͵ܫlTb^d߷7|W_*g^+:<5vX=u&_ +)?<{vK1D_32___5Jex\bӜ ʞ!p#V)|\ɾEѡzδTcCuNog3Qu4LS}ߧD +|i4헟ϜmZ_T?纘~2;m +4lUQqn"3y=gXS_=7_yO/HX`'6?gF^b̢[f5~䑰&_ +#.י9,IW-"j< +KF,_vi;RgtX9m8;S˃Sf3le!whxΣKW՝Tm7kj"ς7׿WH8g5VUykJ\??B-IM|'X{ɣ]N\lI.r7aρ| ?OZn-{o~RlnM%X8~_ +y b/%o%z_/mkRϯ+Xλb7~K6ڷ(zxtza:q\~]ݙ<04lޞFF1}٧]g֗+Z9_p՜\gh;O}b +O,RO nbO9"YSS"X>[ ߥdq+;i˵cBÿ|/]ɺ칉ZfF`ej4^Rō0å۝.=U>}{ 3\hI)oL x̹^1ꙹ[^m`0n腾‹9Ywuv?6)sa<ϴ>W-]>6R4{(w6Ti>+'U.{kf6ܴ Oҟ{a΢Vn^ySU5.{+'Wڰ8>gb)ݍBA1_7_kۖ3 .KY#~zOȭ_vdmLy`5X <7ϯ7̒>uO}Y; +-[@u\׃\[cU<8?v(kz=b0|sD7O+jS Y*Oe~[ Cn;zYsS[9V|Xm2ʶwB\}壟s1knE翜w%Wm +uN6쿐q؈+ߧ&3u맬w0%q=Vv>j~'%,zeKYWE\yض[ڷ0u6reJ5y$OOխ Ϭ:x˵3b[88^߹f2ڐ4V#GM>`_5s.v?.2ow4[TR +I6s-y!z'EDԛ(;Qm.2;ޭd) 2A43\;k볃9L-nqԦg]egegX'mp}iyD`U웂rJ'Omgڢ[O9SſS%CVxwbԃ#ܮK%tcl,UOZ)̭f:bvrRW>\l<Ӡ}? ޸[kckܣ@Z%ƥKMZf{zD wEꟺ{`΂3o u||+?,~kyHۨr\~yF.1Wy#v,6lh/vkoN]|^;#Ȟ ,}il(}FjuQAtšT_OO+,Hh/J1oy]4*`|?LKVt=`u^ux]}hə+|{'jȫ7}j +S=r⃰w}'N[e/Hz56O0|kwEħkYORH)^*ݐ]x٤x>ރ)qSMF3;3rlLEW,>SMwo\زۻS囏8}0}Vfq_?s摷*vWV~@[KwOm__ѲiٓNGI3- w|erY}urz +g +Gjkr&=-?e˙)f*;>K҄է~;_"?*, ζK\mۤXt|=w=|Qew|uLC3ߚ6qczm'NMRPP;S/H9z\$*Hfk<}{Dլl۝"OtJ +S~ׄsW,<Ǩ5`˅w.s^m:-S+oo{n͘*3ˣkd.|ٰ{bilyߒ-5zQ-4(W Xmz[ͮ8nҺU!W=^M=o=5 ٽMf7 ښWφ,:Tk;q]4-1g7MXƵg[yowm@k[μ]9ͬpl~빤ۭC}{ypi"O-pf0Ĝݾ'8Jjah-hw6渗.4XAœMͧ~Eq_յB$<'v-Kjlq5ZNsj/cξ=7ueO`SgX5i#&bf)ME>*ط/Aqt#gMYAUDf; ,9^v#!:G}7r+[ w,?s{U7'Icqޥ*'̼Klf]Əu>uLwghEb>p[{\*DJe;ξ윕6oݦT:Ǭ3 5K"DL_YJbǻVy,9C'-,{7#MQw\zko}bRs.߽΀UÓߦNŸڭ?R?ݿm$~ji@֒ M۞>v~3Y9og:L[Vh2U VV û/3_x6rYgBvoibb%v'_?4Ι9oړ`(f]kflѱuЯ7.ݱ!=mڳOϝbkWV+(u܅/;;vw۬E31uL^oǦFg,xV5S-pu>gˎ%bEj>Z7Oag҉Wm7?wOuOfٕSIvz4wז]]Bǟ?{O<%aŮٗ znwo7Ҏ:1]TF*Se7w[+lx 4 Um_ɲW:/ ڬWr`b/8VЧ!m¬^fwoۋ&6d.2{"YoT~ F׹lsy7 $:+Z[e L2 +>/}"wc5.ek5V:5^)f?_WyGĢW[X#v4gMg`t>{"WIs[[^+eg?Yӹ9Ϗ +9dRB-朂ռ;/1;ciU]f2ݷG[)nd pJVֺ*x#[vciɾsS}~iΣ\9,ZS,+r`ҵ_yGOl\-S]8noN6iMY vw4{_)LK  ?lWW|a✾/+\1VeE=LdH/<=oyu#Sa7rf6v-~Ѯ{1+l(uͪ}.o s6 +IX +qV 3O??aǹBkveؖ{mfh~_y7#7yIXK˪:Æ^6/r|:lߺ:WOjYatIߢCm3J|˽e3I{LNw~+SE_e[<*Nڑ۵pަmќ\&ՙlo5 {ߖ7NrVrmNK.Ynoe*xZow}Kfaӯ,LҴPI3F Ou-E)\:'5ZŹn[ەdmY~Ȓ&>ͼi?MRekM/h,b]ig?Yb>1?̛)_y~|0ݹzV˿o{6^GOLW}ږ~o92 Wyi>/\6'wkwk]vok}=yE< +sSYpYyM;W7F|ݚUgh夝qf5MƜTH^߯1AO_ci w׫9 Nh#NĂ\#B?-{Ӊ_0Vg,3~{rg̊(oN)bQFnT{ +ߕթ,{p֦eK4wɖ2MIGvYԊ/r[, +6Ydή۬N5J#r+̐o‹/̙iF-a߼f9^qFܐ$;=LsDٵv,{XryO +82uTG%&_PsQ?f̨kO3nyuf5x߃+^ů[< 1KY*:Qo_zJBmXn hzq^~ϟ];|8NZ0zm.{kR"X{Ýˬᙓ`ӴG¦Mcz#omΔS,]ŜںT $Xr)&Wԯ(<8Dfd>9a{)WeЩ;Z*?I5̠⛂B3{*|:1= +-v#5RXT Nmܶb~[ȴ9XR3۱5])ȹhܒEj wis=}ulL25/x44M|xc:s eSLKgO:OUL[k#bk_WyYzmΨROo z̤_$đ<}!-b?`?%>s'}=~kcbCֺto +EcTd5[eU?5%:)2>%&AoiZ߫ĕ=} '0 BDS*`k^x"6dm+}%" +|tY"p3kt޳Me֟of$ao׻YzuX-,޾㙁*I{,MmbvrY q8:pk~^@웾<{_W?ƢH'o,Hk+ \ӕ|g{݋gB.]̳#̦wNW,=4ئ{Z/);o4(_:~ǧm3w+=-PtMdMӳ '{*>u*1kg=^rgD,-Z'\Uw~Ĩm\7ńV8W9sD;6Z`5?D{ gfqtk{;U7$'x:ᲘV#u\0Wy ;2Mg;aJe̙owpX|swiןм[rw(PhSiYL SW[aif&[Nò,ր p] B~e/$rޣE^2 ++#pn5l~>w(g:}{C5d!!hZ9A+Or-Vܱ踗WW #m[OZ[ώ|vVcߺk/9yvc1Jq=_'2YY[_?.^,ƥ3[s MgYk׏:<{C 5J$s>t˯@K>\q߃&fLpۖ"t0DFmqU ++m[,a|Z׳n~ixW%Jpr'{wi{d:>'V/';kRyx|蟒<}[TߛU2UYw +UE.~G\bnݧۜ3N_4F&V\@3=|tMf(,HwܩOW0,Yr,b‚Jq{0ٿ1Va?Z!6 k^}u{U dg$};;e1~oUᦣ5I;ijޝw)]0y1s5sݶےRL/"Y^h8Q `[i iLK N:.~|ߠkuٍwvfgcovo.g9_=ږuh=u si+<}:pikv (Z.X{ɣI_i_Uӕ+$:VRf`e}fEpxw&",sk0ϵPTA爟GOM-xɖ4Mr|vk?&6?mOVK+4*N_~ɝo4-5'r^nC!歺E[7wX:kg+GdCxWOvMXJyϬaqIJk~O+Տ&[=}S7y8DB͇O+ zZ~wT:OYuw٠K47bmounjտz9w/-zN>vu0r += *NU-zOnG:}<}IԔkZF8LǶs +,p٢U%[v_ȯ6Y6AEIsV Faw)̞z{jw[Y;Slvrz]y'jؗ} {t6ϰFiseTj{asOL>I +7M{(+)w/+.xUd Z^8}˫I'z0L}#.wzFJZ}^gj9kwXa~ΜCZ6떝Nqn2sz2R͚ZlU.<{kͮ-Wiw쟫7Yr|HIVNgyS%xu*I|3rhbʷ_~K.?[ΒK:w4nϪ1ڏJTOZ^ػuEeI<]ʵ]pTn+[3[m|_`[w«Oȷ+nUH F?6[Ua;vt˫ M_zeԨ9Gޖy:+Zj};~*-n!*=F{kgK2<arz* ,;xO _`so~uK$""Wc[a&쨰'"4ػxšz'k^D{Vgny>7LI;XF|P c+vrQ䅳[L<bݖ1\Dogj>e_rDxpQ{pGi1?ls=<1і[+_Zc&R1ݛva!R[e?9`JLM5Sv-M0 Vd&/]_8?w7?L -Q8 +k]~iKޔvҌrk8=yfڅ7q-ø֢{mM}k^rp+dyZ?a~ +_ti?]/SD#'K(LJ)~oup^N/dli7cuέ|ztk?9d*Zy:H xlYg +t e +JI}պjG>}%S>mi[}ͫ^ڷÞNqYabt_ [u-RyՓo.D();w_/_-w}OB}B,ey}kە^\vs^ǪiU3}8?ࢦɅjg7L(qIOU> a'wێ5.S:]8LI]/~~:1W껿*3['23c[k{8<'qmSa*gT|WmBU+UCR^U̔3Ml?6 } kd|;Ws􅿿~q1g"ے85k`2_$(6K,#ܗ/$xH|&}+ļ]E{n޾RDQbb>m{nyx=eG7..L%Oݱ*PQU}'o.6`ݙttduyCJᒷ9zXABc[\ +:wB{꣉<_F<'0D) 4w̔ds{U?} |qǓ34 WL|,݇핦YWooRU7}oUW^퓔`u;Z67ʆ੡iML5=Xd2yQjV;.im>;^G[%9_?kM}Jh9{^EkTiח϶lTou@dMV?㴋ww_! w~շJb0TƎζٷ5Zv* ob`u%y>5my{gwB4~Vf7ɟ(Vl1|a_EK_?0:' 1}rO%Ñ^k3˹;9k_'Ta9첹v8gK캅7{|Vr}Ov!OVI ^Dlo;.xS{z~z՟Vn܍vp{B6ȸA\a7/|\oBN>w;]τQbN}r%mo_wuǦi5)܍#+7)8nc[5}lmK{r=b/Ύɛsw˲WLfbxT7m7{hV?ճHY/m{Z?dϙ3ն]ݓA)W>0Mf׽)')O}j-`#g= +݉e%:X/9JDw}w/pmY;ݟ9զB̮[?%N>mjkg_c7W +1&=x0, +_o[.=?j}f0}|vEfyIM3ְ*p3viy^)۶HK,ߤ##uߙ-x^w5w5%^^-IEAfLw[ _cN^p[-ٓzꤟη{g>a ++sD{Q6_5X%XlG[!o'~j|W%{0gzW[pQϫ߈L+PxaR#Nd 8ϲ FG>\S2;Þ:3WͶ>p>^Y.f_H}#;w[b_:}~nNiٴ 7M-+9DJ̈́&9mV +l;/^6nQ;=_tz _,->bty->'G =f*cjeg|!oۑ\i.U{sˇ){Ig𿌱aDi?Îy߳\0^/uV#I+Txoc_._etűZ['^=+*q©~OlՔC d|`k[at,9ے'T>=wűŵ4EH .m!Ob{s~0jGœ7~ fzE}z{?ޛxaקXñu&w)t {ꟘG', *+j~]#++kOя?>lNw>ueIR-c~T&__PI,sp֘bxB|zٲ~΢.*)5{!G~<圚5勫UU2ߗpksM~\za&/2g.]K>;IMݮ94_,N(m^w7c咟lӝ_, Oc,0ywW_95cWʚԝ=I1/_YL=m-`!<'x_>UT6K^׭yNg}W'>ٸޢ$v%}z+g;-x9dasB˫})?*ؤJ'߰a"n11xU?Ǣ+.3t^֋a]}_&ܓD'Ň Ih&6+ʚN;nf$׋ZIE\٥a^)ٷ[#y3Wes?"8rQE*Տ]n7ggs7Q*I.Ҡos-j&2ms#/aN2j-bCozTwrVF$O:zV/W-+wx끅of.xw[Χ],B5ҠBt%J"4_(V꛶佝V)%6qmR|7학N-2g1R_{Jϵ|^ /l.'[sI&ڛ\.{hٙzj 3c>z>kĖo gdYӚ ZB Wr{vΜk]↍G˒4d.yѿcZnxӿcu]ڝWqEߙ;_Tsz[)%ìNWrTyM 句|J>;ᢽN??VЯ>4sɅ8{/lq -(gQ7;@W:al\Q%Ńr'O\PɁ) +75huA!5V"2(:;E<1ŭ"2Ow,)6+,P6ʵ˭vYy;v/Ϋ{;^KruG+yloo|IEߝ;wkd̺aYw׼g47޼62Gb<*ȻŸ03eܢ:VBc36q{a6v*[kvί=mwfí;1=_УnYyUgIJԋY53LZч& +jPsč",S_&XM >bT:~k#,P-k*{ZvrXNOjIXt1O`R7EaoXȫbkgbx߷׫VTd/s,9ĉ +wW|=V;a{:[ :,V7SWJ8dQ2lgM "җ=&ag KS:亾r zC˙YX::}U]Z[!}˂6rϜ]cT!mN .(=],ڵm0M{ û'h0\ƖZ*cs=Rxɷu>'r׹>]yܵ%l͖{NiMaS6k׉yc5T9"lﱟviݓ|`OvȥE9i#|Ǫ翷:/Wgb.] +4}* aXͰ~{g/ºǸo%ݲI1wrgZD,ڳmEo[&|)A٫g.(tfS[󳯧7+($eXL Vx86|ɬC&~;]z[_WGIw=(_y^Ӳ__ڦEkgo-5Ϳ۷--߮2&j KqNu hp&k-%I;RX{}ŮGO5uD>M >~&-I*Wz&{CeKVĨ&tq;j;F'շ^g6Byy]I}鹒}n\n#P|Mk̖D cxV/z;I* ( c~x7% ~S[u_V|dr\\jF(GA &!!+6XT5 +fH~oqgDznhA2i-/_H&-YOH?M| iVFO]*_Spef%6m}pǔ{5OZYJUEGe{ΙU$LBj꺪 ˮ+*{ZNۺΪ^56W!;s۪~MgKTāu'&Lz9kK簷ɺeXE?zKAOlpͲg oo:(M`A]Go{cBxoݱ AnZ6:3ٿۢ >r)sxdeiVw#ܨ;cu+\Rw%3sW5,yk/ڠRcq/W2Y[o6̋?Qdr8[Nm1?Y2A Mmn*!ERZ yy/<-݇/XgWi|`{E_9=(sB9KRG*vD\}2iɺ XCug,ydoS6(8]ƺG3EJ4uqou7ޞPxxˌU|Nk#u>.XfY'NTs"LeKOn +u 7[wV6W:+Ϛ>US^_^-s4:2zS>w_]aN׎ +~M]~ɒK[vsޒX4{bwPd]˫[?XNsbpcWd{Iƙ&. Os8lM<͚ xV^sG ]R?>ֳYʣ.|=L)LS30_`Y',s5ÙIwjV7Oر4u/?=8׊!/8,BpceٶKe~}޸'GY&Q%Gβ=ֳӻlZh;l!wc.՜t]>׻Zܪkpi_ +pyܛ?S? -tFKrΟ%wofZ2濨|nxm[n_鼥C;#q4oZ}{VxM&>'$[[Īj+ڳP/xqvGУk]%l_imWTk?&IS$<*iF&Cfկۊ_&F}㓹s-ȰfA 2?zmjvM ]nXsZf̧|\eܼn p cvOҭmŠK,}:XeU 7'[5Թ뿱=޳'HG#ᾟ{.2s|a:Szuo3\2p0|zےso[ewjXϳ6Þl +GlXP#E6\^(,3&+o6QTOK&'K~Ʀ=v%im2]cwޟ-^퓙7UtA#݇$_Hݧ?Dl+ rΜ\8U׷("NZt-ʿ> +'eOٶ,S[#!D'V?7I'y1cބ/^>hP^,Ug|K=ދͶgo;J6X^<1ԣ?jv̳im]puV 5MUi37|T_+4s2.WӈY󖞉fߤ5jΜɍǵMK}] +a4Uy'va,=?YbJrG o Ȇ+NMݪsdxX1u zEeu+ϴ>}5u:\&v0LdL38[aT g<)a$WsmM6#Ͱy9fLI[ ?Iognnx0Yo&lĹ#2\\ӥ×⓶Z[>Zu|xŻ==DuXh?dzAo녩;eFuU95]q;G6YEU]?Jz),P~R7>}ؖvj tuc櫰OwS@6GDl҂ʼ$?H*ׂyဥKm{?_l +b>阻v3zOMK>-;3޹&t_u-*&\Υvx\}lV7 +fʪWP(qeR8Fwk 3@Q{u|z>Tg<ޕ'~6Wݺo1aד_5Uu\@{{ O^_R.eF۟.~mR5{Mx [_kƽk˔Uc2gNvL"G<|+sn]#ٱxog7j+&\+\{8Mg:>~Qv;ik4oR>e]붶d(^;˝5~nUr^M|~X_AHWYk7J7>3eHյ2 ..V~"-ݖ'R-E2=f޺+*4mj+~k >]=;j/J'O0n{nUEYl`x?*a&?`(^ǣ0MxC{y=]3v Jm:3l]5=ug>;x7mm[ejM돓^(Mhe}"}<*ӞWD=b:*/!>}\re|3=xOwc77?{w-k:=6.}/5rK▹?I=1_ϬnCz +-;\ż尃3O$&6Z.+T(),xl=s3F>A}ָYqx2oOxogrXp}ƣZ&:>b\ I F^i&gؕog^뺥AkruOnEkm{#6d%^쉷ئ=1iy75 Uyo-d9 3 +cgYhW敛(|@Z\Lu늎<0Ynclyl]'N.v4@%gڲg61ҎKw]#3E:ۜ;wmcC™i&M2lgT7O4IG3Ʒnݼ^RS%Sn?w.ͽR2-yœS _} ڭ^2rh'j{26Rdۺos祋Tջ,[(ymW>5e%WWc6s=&Zlڝe10c7c5?[\~PUb!Y. ~5BUu?/Q R[ӾeG ]ϪNxV6㥟~Ǿ#53ٳr N,۱~'Ukߍv>v'yCƳ+ފ<]uˤW.9$£e/dmLf+ea9;>n%|1p#ӀWw.~$uc}'pN3ުc' aye}qej\q/f)))qjŷ `n}qiܯ7`B70ۑKZJ3ĿY­}#45/KUSOඵ +K֧N̸͑,3!)Zpz]F \s|V1MȞo:̳\k:xs->_$YKKYY[>nzu~/y3MaQ}m1 ]T}i[ɞNo?[<]YRG65y}ķ{QsG R7X.wmϟS:Lo]/nݟa?3>pysL#w[>fO(9Z,Ēl1DCzҁ'*ȴ5.}hƔL}Lٿy}M[ȋ 6l`[U|bBݧ˪lj'M Hf}7Y•tOUtTH=M_;rSf c琻+}'̵?OJݓf +?73nK+EGV~y"jͬSeev2Vyvߚ%O"woE5le7v4$v0|d+Е,.8 +]RaA׷dٶ6,vզ &]г+rD߾5O~M Z,~ﲊiX[D?& 2RӸ!:~[}ଙCc*wpFoNRk/|.QH%B۩0?D{N٭'Ԙu Y _|>hh떊(Xu&E9m[iѮ2 V=Y3wvOp%s*74޼n;'a0>}ۦ,2t0Qrb_su.dFWt?˩S\-\t[3a e{Wz9evvݷ]|ۃf}a7SZoQhҹ3^lL>ysa4Q%m\xBJ@ uHUe'.?q7TeڟEWs-xwmXaݯԯ,ٸ!6nkqo]]fs3>wHZ>cZ5e)o7X=v]杔v)gq\|Lw56xUk_6ybK'W L:Mm]f'z՟(Xu܊š7z<{ی5O{>*\a ՜ݟKpVB.$-ڦ-_{P.gΉR.7z0f02\_"m5[./sc\wY@۾ʹ{3%+]YO~xk ubvE'.KYR:G٦-~>jѣ}_e_dZlWUOX1FXpARVmƓf<.{iSY>~B益s_|%pGBq;#7<75u{&ɬENǛ-k*/Xyr9,'X(&V V/|[c$R+"{E?;erw|ˬU1t#Mio:4Ec6?Ҭay1a8}ZjUi`N;dܫs-]^6:} uC\-|yW׍'X5u~b/[m[;iٖmbщLӥ/| @'ģqE*6D2rGgS&;g#on8mס +ڷx2Vy^Odk[ymNJwb\##Ή-#1t6j#dꄊ~?Y6~9eZmȟss;k&j;owUn'TfM 6mRV^ҽ=YTov,=>-j@{oޱwIZ^I1Ox(^X<{߷E<tE@{!N6n=q´^v?yp _ n._TdVDH|潼N7S4.x~jcߓsHԉk[p6NMg  +'r[ŵ=f>|+3|mٓҽGI׏E:cj~r,w름ͱe)Ng2=zݼ,\^ok"W񜷴lh^wz>;\4V]k:7mIaV{ۊ%f]q!oԻm37M\D\]I|I?*+N3Xp;.ݬ5󣽢T{l\~Vg֊Qb{㦯nY7NI!^Ϋ^TcQU59tEY2oL^zM~6J/G:2^Yl s%V7. |HsդK2۝xZ) 8u_wYͿPط[,d^{ҬBlK=g<̵@iCo\l{3)ˏjkSes&=X͊Qt|uX3X{Z#l\5-VL9Mz'%Ky0'1jD/M>`v֞}0NmZ#_vWND}/_Oښm*i!g49M޽3 ~oOYtaۓMI* +j]gd3K9Ӎp"n{Χv5yBwΖ%a9= |mϞ˥hi~yÊMr&ܓycQI;澻h2u6K"m:Q37vӬ6<ބ=UxucɻrWNyRq;ь{|KNf]pWrT}~v,@鏾xcbk3%|+g {l|ٺV͍kX}P۬O!d] g5TZr]O$%,~7sSj]-wx"PM7#6κ2;N2}yŶ=̗-͢\bRԻo:y\cшV9m2#u%V +nǘ5W`w~ScϑY 3,RlL7Ngz\HY(IǽxVwާ1O6/R6;EwV1|:YG,3t|a͒w8J*nsZ)S\Jx;9-x&hSWw{q[:>y]r௯uŻknO챧ATfy'r9NΓ9hSPLyN6˽8n攴Fqo49&iT<+!5΄ѹ|t{l1Ipڟ1g l477L:p+2_O͈, ֋%y!"N9OQX`׼BLȟ*]I{y5׿\6HKO^j$j)=[7jY顣c?n䥎f.9M{'2ޗ9er_\zQq;qwf=3Ido vxcS jgFٻ\Yugm/ϴyԲ")KܮY?=So+DQğ*?ӟ;!k:˽'1|i/zx,CsW~z+TO1ض-ꟿn^s{ +fUVΊKqjQ2w&{9M^Ħ:)' +,bqDz.aTLdֻ^zOUmjR,]t/ziiVjvϽsój{ŻOw-{׮%+Wmi`fn+qXۤ E=s25nmr!G z={^wBm &;CK#-zʠno|]a:V8vg3[D>/a}r-s'nl$(n1;']7Xrjڂ߲+3ʦ0cVSPh3bLz1m}INJSr3$O9Px`W<7 +Gʔ9Mklx24X.zd2EFϚ|aǙ9IՓWKčbۚ\lkVėnQ!ÝNA +_K-t~R!ë=Дnzѭ|ތyM D[Y#!_`Y V89 6 +r%Xs_DV +f/rٓqyi}ϥ +yvbg5 +GTB]޾oN5W%̪;aղU.Uo4JUTw6SêׇhwV:0 +/y3+R{TPcgP{ǷmHzvw׶"8DVZkW,ܾTo+wAo1~R!1b x:K/'Laq_EdWW;Muqڹƴ7~cq~ϠWٶy#fu2+͸0+H<ԣoG=)U2q{g{m8O_)A9f]qH+mbyJ6Op.}5ǗEVaIv\zsUן^h(2eV]؍]Z"ų!m?bk:}hQ?o_7cҵ'4Zf<9mkrN~}sVIO>nl7g˶[7%yЮW:bEM٫4gywVK+m8p [r{X Y9zWɊ;~-$JrkҳʭUYw6Xq'u.3~}vkvpteM׆VIǺ៟߿kZo5U;xIϘݺt>kW?W3E le>&3!}_%GwŪIWV\"=ܖw4#/ dz/+X8ϳ^ұ3G 4oɲY۝~ɭ=WZgrއGRm/ 1Cwur_Fz?B +Lgs"ҭ> |^VD[}{)ZjT[ժ׭ZܣĤK",*-u8LKbɍ?`|~uKmjG<,Vyڥ,_ctKկχDinZ>)g.9~coUo^ˤ, *ɬo%E [;p1ٸZY(_5;gwm`ffZsO^)|}u;2S9Ɵ٘m9iu2QTK6Y0nӨ6䟱{Ygy|z.v~ͫ KT7{©Yݫ{n}f 8ljD;t- ȥ%feOŬ8?dTg o 4"E7o,skژLLi>b}Po͹CmqƼvW}uFBk ۹u]W-kpQ&swiWvs.2czia))s]+6Ո\q#C"yLlsosGKvYsFO3b%;RVT(8Lb9<|ri,Ou8ȯjx(`!Lۣ +-/o#MY6l/'w(~t [.;BI7AނqմiWw}jgYzvMSQjoZ`Xð+y*^ _cVkˤ. 93Ui[/ݝǭS"_pZay|.Kil/tlۻjϦDu;Ӻ*<қ/3yEgf&&MIC)Idƥ.elZ?wΙb'{m([Z6n ^\w U/ ?.Ʋ)bZ_sy>msi3fiuY7NM0s7paj{E{^XzbOvf^5;Ef [{v5ovHJLYs:IjmٞeϾnlo׃Z~.o3jx8d]f ӕkuSжkdˌL&48P#՛v?:VÆiŻ687XIΎD!nfrNzj/6QJտz"agb_/`틚{d3fyl~Nb]Სr'a5N,hq!3kROsl|y.abrq9~UR6ɓfr\y7"^Smƺo;M?c< +rDʎY?mͣ)=M)G湈~.w`秌S NZR8aun=OѶ-nRYU{W 91t2߲<79/s-޴L6еOO"J\iƳc߿nެ3=m{RLWa͸z_EegF. q $_kvѳ+'5UY|lʬ+?|yfJ,9W?:cŽVvD~Z;`m墦LwT鿋nvx[¤Zy۾}fz5{W<Ť@Y[|ӯ4QQT8FPwٴ.\xFa駇'Ÿ'+-sʮ7qY'.qa^)rp,V9Y{ؿdI/_F.Z7b}#;o bzt^Dk +9f)ZnIDi+>9%ٲ'pp65M31'݃Qswš֠cBl><Ɉˋ^LJc-{z?[2c3:* bʺmͼ`M!zwĊxq;M咼xK~I%??QקMyOjOAf*&)LI<zb}su‡;\X _8o43ƂjKuJk,C71XײkޢfӾ?d8)w}8ժй,=ߴMYdg޿:pn`N٪Ki*^@hŤV? ,y޸-|czG&wnfkc`VTrNnw)tƸgq'=m-]٦Ή5}:iuܿZJtkRtM +ŨXSa%>o▮ᙠ'76KN=2ckɁl%MF1W\O߸He޳Ur%qH~xN{(,pt~mI;z+C5^=J +3MpU?$䥩1|9cbNY+/yb- R/0b9gnz~:yh罟eEa [9 4 /z)娽Sq6]K68hx/;f}FE2|K̝#^lnz_~x뗛IŴ_U=v=YfeQIOJf1tX{rQL癌U'RqOV RfII'}Js~- ~{3K:%nwォэ?˹0<uZlkdG> +\ǥ~̸cp +wpM?}\yS>|L?}`U7_l+ k}Nvk6^~Q(w%;)OwɁn7lϚf.\C'3U)ɳ ނkgsn3=3J Y\s ٳwxdˮotʹ n=+ڮj#p}ks~~j,ˌ7x͆~{)(75y.3yZz%nWn\)斒1[ϗYvwֲ|Ϙ$]vdϬps+~5Kxedv5٪|oP7n`uiRzf]_s lPsO>y;5+_Y9Pɤ/g6&I:qNmSlڿcQY?Bbg>z[ߨ_~mV͘u0wأ\I߬w\bgE-\;7}^f#%GfLx>{3ԏ쿽Bʒitc5KN=FfzwG񽱉.}X;Ə]5Iz"3C؜׿z̬IwM{R#El[r}̤ک>[7,_z)&V9c_nGyM2Im6Kz/ea҉{ns|N+͂LV[h<[Mmҡ+[0ݔ|4gүCϸ~|/+d)czW*jpߞKU14)xFr]rr˲+?t{+aN>vߘqz9LXֱth;YqR-=:,Xzw ?b vF[rG*VK{j7D˅W>W'rW=vhMooa9-{]ά;+&65[*7.{޾}{Wƒ_O>ho=3$O1}NrDn3 +39{nִi>l$!l]8G~N,ґ:m͊_pV,>'.dgfmikop9'UY7ދu,^ԩk: ';>~w-28twN+9n vX\#Ϸy[g_[}u*R]&u_7e볻ާ%9;.k>~oe Ys2u~tORy2wef-{xsſksQo~UC;/O(CM@N7.dU]a,lJd+ +LW3I{ժ'WD8Ca%{Bdbo8-ͧ~'LnN竼;mg!&#gn+qC?W;i?Eo21K5_\;Lm-_:fٸ'{K٤PsI.b$Fvk/9';{{&6K- + +iv +2/(]!?9A傄TY^y; {g\6`޽O؋]R;ñLY/d3鋺_XiVU\/bκj%/O8@C7`})eO9L`ż@*eLfǶeNfeܫ屏se\0A-+2N}oYgqѳŗb~nL{c?q_h^Ӝ'tv!j!W[k߹WxO \-G:fUZw1t,yE\JYW]pd/>gEvUĭվ*x~ypi]ӗjbSE WoMHcgvKD)֭:(>r3xzIr,cޯhazLCe<[@C7' ^{'.rNIؿ~Q{OLU54]Ds۾qR'|nxMnUǦ+Ӓ~͋1'ϛ<#w͡E!|;Ѿ|[+ܦzΉշ 7߆aZb}eځ)ɭN9}5黒ɛ]=]m"Ъ}Sl#E?y^喩ϯ[Lq5:׭ 5MEԇ/W'")f٬O$]uVֲb*n9ř~ox'Wjvn,M'qְbᦝvyɻۍ3RGqWtďBmlO4/n| +4bWiKR}5W]Skzd^̒eMhK}Ee#u|G&T/=r9s:eRӃ+EσkWKWlUqϲG%3m%tc_:tbmW9ݏL*w;C86oڧ8׸ NDڬ#e+%^Y/byߨ+2jޏ܌KFXSl9ۅ_CyߚDֻ4\rlז "XgIiůA!yn E;OG ݰIҕ+όdi۰sϻOtL®5rۉ$n49/htvI篪4X j\?, 2tɄ{"*ڿx,sIϘbk#(4 ڼ(/ᙌgNMm{y[,<%"u梪[} j+M)wˊc!nO>i[ ѝ?̲|L[WtŘE8e[,7e驀`_M~ +h83me[LsλhoSh;k/ƽ9U1;P&sz7kj߲d[|׊v-I6>26ӿԥubK={BpEU^Z{>U:/¹׶jyrd[~v|r[6/ܣOW4Mfe_gtp%7Ŀa]cnQq7gZ[?W_.p!Sn9-KE QZƫsS5U3i븭8xz%)=l%{K% o=onе +=FTq1]oA ލb)r?5m7Uz$m8;'Kuy߭آϻyәtjeG7.*1{X9׷x3[@D$fGR㬾ǹ % ͞ ELX8unЭ' Kߕ}~nr6^jZsw[ɽt~17kRM7f?콱'Ǜ ~(g*=|q.gb[K;K}qAīp8I8d /7Uh!aiMe2y*#yw^ۼltoh>3>U_(Z?ƙXsOo>}{|!g5WG-۞9㗐U2~7nZݘF|ncӑ̖Tf^>Q5KtNkM?G褖v[Y37T^R~?Iʹ: R#pwu^Mۊ 9߸{}{xzG}?w;G{;g[-Y![3ɼOw_OW]~wVYUYA;ԟq_Y+ws E7tȿ4b+?vf}IWdm}o-9#7le'nNmk_[7%3\w^R\WVl3tve[O8p[)kqf%yw /Cm=n-by筟 -៝p +Es$^f[)Ggꚜeՙ.r^{MY%䖱DbNdQꯊčd]V2sT5<˷iG->wv?K +}薼$T^ Y{Tv͉WLn۞ff*f/}|/GΘN}633/2fn3OatWԫ?T75ה9B}o ,m;/xۢ5.sߤpՎCruV|+ նs/o:&+~J`$xD66oI97P?1'csxHSkPƻOMҺLVx=x"μ<ӄ`y{%,/A"_siyc^ ,^ukxDe;~wԧzZ{aotQ9vٯS/ 3K^oi zGTOV` +#e }=_uJhZfDN9#uSʛs.xq8- *958H8i T dpG*?mN)^ÈAqr_Nv}\:syŲW>KoV9.'%Ͱ*;lMk)[}avz?3o<9Gg޿)ֿmUndrLڔ+BB;2n}>e…NW#͝xaˮOWp˝1vk$\'jzϝoVknOƛ8)nɳO/FpֶVŭ}֐Yב[̥e,Qwg.2ceP\"Av{ _>w?r%i7> dE]QtY5s NpΑ3|I_OX8i'|_JE49;Dme0.}叹B_׌3/f{/ _ǻqv+~u8O$I'o.ӿ ߿DV0 +|[*xq:^I 5/:]z< 'sNRR|]zՔ?̷LLM$9c#3;~:\RP^JsNimmuLFiY5~պfYnisgCK;?[ė/67\n Wg(Y1?.Rj]oUj6Ei5.#7Ps^-x36^RQb/3D[j;`gn5[gxy{,es㫄+Me|겐Ym)w_/ʲqhcEVd.>u ˞Twy6뢟_7g k+;r>Y3mwOm?__y*oj*dtԌ_^[꾔kӶ~>@JIӔ _[|Zwvَrrj'_o\mץ}OOR9y.4^9IMϩ|bjkͱS+NZU3.s_E'<,~ +myػ<; ;#;=9}bphea^V?b ?PmJWᣩ>'Խn>AmgWMGĴ̼rx[~ +.\7Y K?gbLɟS{8d^M|!}bM+o|?cήp :+> vj)_sg銟VxppΙS^g:ʌ:1h~-EٻZ?}&kf++yW|`LӍ{N۔io]ձg`=Yڋ=;tMPĎI|G;7qVqW١޿".M{6)F*?龡hULOB [c|=i= ENz(4Ŧm5)5+Z /Z+(19%göK<]#_ܦ>ޥ S\q$vϏddkWjLS] X| +׿ݪi7c"f7z(8+m x,\4OuSD3w_?7yoz +- > {;B n5T^a[}JW8-_uG- ο9R7I + +neitlrc$vνroڄE+xڤ^IԈ5bY3Nl}o!*w\"\Gߺܹz#Uoh\*Z1/滟ֶ~gUV=ۏBn-^IpZh&SS.o:N{kU]ݳL?xw NS_VsUuM+ǰv|-'oNͿ]vs7DBTKorUb|.֦p6Vѳ +3>-e*Μ |ڶL|E}ڢ~Kaeؽ%>lr2^R_(h޾#_*3?>=$.${Md]?n&Z/shԇ}Li/iyt񒻋WU2ysdIy&޴/؏smYii3g-eMuM.=>ǫ? Zzp+&MkwZMxu!wqիK[#/^ +}̟)kgT1~J5..(зlW݄/{mma_d慂vMj7SwP5ꇏkό9b5n /?X'+p˴$CpX/qכf +5ɾ̠sq6GEkTߧ3} ۬ٻYLO>(Ysv6Ԕp$Le#V}}BݭtZ wV֭R|=yECN'uܷbM6S^-g{7u W9' +9l4?yG +˗v4e'^ǽy˝?gkE70|~x#Kg$Q93k%_>.10/9yCg_ge\.9.&EE_u|I+%xfMo+D, ʟ.I*1~ߝlWз0ߟ9oNkh٦/9w{^1d5ڷPzKMIoX>O9.9|.w=}b]s`'oN(?yI-}Ų r^|o1=`#'|m+dt{\6K6,Q=}ɯeYD\YMYbnhTߩ4sׅoWo_j,~nʋ[ ;_}xe*rSU_>{"ͯ֋^:']gU? +WdS`&>iRCҋ]{:ӌsPRjYjcO/.{|mŧvbac+,7Uo|/ ZwwmYLjfte}uԺvJe9tC޾GOqqȿo\a>>?:FއW<U{ _.Vi}wnö 6ۦX~8Y3j֟hw֌Y gN<{f?+wm׫8Lϭ1|tLŇ^)~yu+on=};e;-bkշ*<7){cn|fZ26I_$2dN>zZbkޥ,zqUWtgl=Í6_қ񫺿,];tkCwiWNpvޕ]Rt_(Ir}cq_ 3߫~oEvq\Z!n'ޖ+~آz͡cq},2|^|Aؑh TU.ỂpdIk۷M:Yw덃.37Z$V,9[1:vLz6;W}PWvꟼ|zŜ Sysz{sWL=bsѼ'OUsp\|eٴ1b%u'ft#Ӷ;Yy3tܾZa9Nm/s;'bSm=K{_M]^k,s^ߞ_M2ZqQZyՆ)ʮYN}>0T9eLWnҶ3g̼v^KvKxEIJ3 %?y;ahKa*>u~K^)j2aozY3u8 9|:yK3 }xh[֥x\yՅlT{V/"[&5c([ixD%\=ߡ.<03'Z>?z>_zzBIvG v<~]袱xZnIS{W|һ}cf~kCP!^u\?[9 I/^dŴ#חIWV?^l,0nGOUH~pCjc6ԉGoޖn!;uw,,MkmLKJ\|npA1 3of +\ %gѝ\ iRWz6Ό.T "04%]βIχdjT=9T܅gK]w-YUbe){AD1߅ |Bٳ=JC}s\IRm}ꕀSW?Vk.};V*Lyp57w?_:]7a) '~!3'd})M^{Y| pY 3Q'\IzQUǗKzo_gƯ.5j$X\M*vqaEMK_r,ʌۢ5,ōKUʟO_^bQiqwD םn]^͟XD w꾯PY^ߛ~FiOLb]$bkҵjk1XfԌjٺy4CܦÙ=mj^vRǩ*֯9cbi?2滺sՐЙ5WǨeuT}I:D?Sy+ *s˾̻|PE\Ǔw7nզ\P~yZ˞;lh VT--bw??,irtS8D 3fk8ϕߘOo}5R^ŰOd ϗqǨ&6ujɽuJ_N[m\' k÷j/nV{އa)%IVVBjb_şf}aBK +;}5*O5+p Ot DyO=VO׳6O/9!E߳nve-{ORRM߷}kwxV\8,Wozy}ƌ2vS6ڕ]Н&' Oڐ$Ey;k#oXNt9r: *Տ~6j/ǒK{47ox_k˩ߜRw<r͖]?~*w(qzk[&m~{լo +-0Ǚ>.RKk̖N>%/>;{fUspϘT+,4{vRuMf5!ؕV_1ERnv9>a"ߤܓ_:Iaǒ7\.M[IB_Rfi ߵǤqWٴe7x籞,)pMUR+&yE{}[O? +=3G_.[?JP{zޒ}6E.Z}a.gNK\[]{cCݸRf h+t ϙO=jj:ωs\W//a\hg%ao_my/3[~y,INU3{:9mm;ަh};ϤN;#9ɿ.l%'>ܳÞClSdɨԶ.3[v竍bgs0/l{+d}ַҞ'%^`إ?&]ǺWezڳ8JvkXB[홐97}~%r.,җ|O>G7>&m__qsH܏CS_˦cYSxͶ}dVen׸y"`weS ,q[>9T ߡe-WY*c{g(B70QR.Qt|,Kv0v38),鮵~<놣YBk}%W\(bg˶q>m;1e;\nzuFB3u݄;%51SRE +_nnH}ӧUGv+[sY^0fW_Hx"bZytCjv梦a:=>2TOZx'9|{7mceExVݧGeO:0eRVs=)XaLlӫP9 ׂ;,ۧ8#u@ʖo۵m %SN7渇9Tu\̚Y3_PRѤgH**yH$coMN6;KOz[.Ne\Œkˮ5Mz t\ruTm:m]YJ]8}gL]+.9w/[Τ0dj2]h[,mr?t M#&̾i,E?w.|?wioe3k33Vk{c"[o?{GbVŋ$Y|Lcwd;2&e4_oyƴfG[q1W_9<"@{zQLD-+/0M;X{kwBn0m>-8wlGg$%٭k,)pݹ[~_s^~汌~sUEW򔟕^+?DsU})h{)-M RvOv_wzjXbeˡ2ѸnqGimݸu_Ok>=05}D?N7왹~Z||U9WSX;tE".otOη05G4u,8r 5%K?!~܆:3߉0|󖣱WV<}5f[_'YݓQn_rg}w9J1?/W=kN3Y'myHܚ3פ褤s1bt}z4ϺeCύ6 D<7^Y&9j-Vwe]V]@59KX^/8Q8ס<'/1G3Ꮔf.Jԑ$pWWo=vCӾ4[i ;O6j. +0o2]5Zwcua9_^f}vJ)v1ל:Q^fKy,#w_u:GtN7VIcRH5V#'}7[?Kۦ˘es;yeR}9T9\޾ytnY=aG‰1FUZ3M<2iɎ5 V՛йȝo鞄svr`䔛T~^MzIc% m`H8 7U^yr_E].ܰ-~dI~2YA_ܤ:BMS 7J_r١ܟVm֛Յn{%UN} ʾCkw;ixu {;|L ']ϼj,i97^&-sSƶu\w8rnsm%#ègdcΘ{T!|Э3wug~+b#y˸wwJGs Dl^USRSmYeC䧎nI|`}Z[8;6 qNn/&O輢X.tNB-eܛ~f96g_{LIږgN5EA86tTG2Z{?Kٮk֦pN} +O_;.+uk nP-@2^=ou**&M?qη rtiK^4μ_b*kg?{˖iFu K֟\π,킩= +RwdrwOf 4vKO϶Y'XSY͌>Kx:8 M4[67 xqǟe/^ޡ0oNԎE{_뺷ʑŐ܀'}E76ˊ*x} ?W4{2o* jm1sʠڸ5cK ]1pj_gXuB-*l9xܦ zNN/yȦm͓OlZ[Acoaxikc#a|H=Cz ?/_X;o|U%V7=UuNm`K\Z-.pb,%vC{XtnJ̹&$]*S!mT3M*]Pg䰛˲cNҿo*}\hţw|>y*[5hi{wd3\=Ѩ`ckϬ1В1nҎʚ>D'S|/8MwqKOۨ3+y5*VΌwR!3a=׏�|շ+hoOpn3n[#Lp+WOq]f$8cSI|~ӾuMvY}qާj{˖s2S"İKVw){_,nӯW3gg"RT1[uK'Nzkfl9t/ޥ\*)+EoٛvI(]>+RkcmKlJXMkW^\ߞhbOǒ +F ^I˷enYPQpi%Uۮ3ר7tq%ʾUj_zUuוo{;uL}͋&K ̑cyDWw_?a%4nI_}s3B%n,yDp+Oxs 韵Nx/QϷۛdti$\Trd-:5Θ㟅_5vg֋:y2:Cox(>f…S=z0;Hμ K#"JyUEׅon<)e?eǏMόRo +!tx!%r~af1NNb3^_>p,WN;=ƿ1M }1-Jx-Ssr\ֵ+yؚ-0dS'.>vhrZ|ti޹ǥYsοIJ{?yaavO7?vˏ,)L}hp=~}ZD$qيj} ++z{G*;EYxsE\.1L'WI]vODXUg>OҶv;n9PwƱObEx:P.Cz3C~9.,tœS%+72KTmMFNɜ0#:qϛn4gY8~S~яs;YQqcbnU_=;CQON6EsY^+-<^+51RL/\yZ}{ u\YrLٕAbWܖ&{ɓBgdZV_- + /T&vraBڹ|v;n|nGQwy_^gy |!~94}_ ,g&qX:,4]&hsRGqN6^\,gb@ޛ߇mV0e+Z +wj`¿buj}qiz_11;Z̷zwPKkϮ^Xru}W5mһϟVX|\ۡsᆱyt(owּmWm5)Q˗D{ړٝ+yb<6+FK5s#ұ,5nSub[{1Bƌkr\tn6&^c*b9ۨAFO߁`;bb&RT߶(QFS.)mrM{FIcz3[}}s+)'QgBYiɶ^:^W1agZ$yeۯnHUy9JO;|ѫr$==맢c?260u1uzQǺԤIsx5ަUkҢ~+>{~u*gcڪs&m7{)#Fbʳ_Ιc>>[rW5YIn@q;nwV:-=stݹ9WkB3M4qN3I>tܳ^-oXb|?A+4 f]\/qz-q~Z1bg@Ƴɋ7v.{eq0qOZ쬵Ew}ʮ}Pō»}Meȑ}(H1-[Rlv6YH^mq}IbM2St`O;iHI=뼼dke>er }W\?>B9W)dW|Jmsy0~Xjʲwe_w;f{q&-^fң2M"UE|v |{DwV>sA<œB%_<;^v-!oK<`^,?럹 ѧ<8X̏y8Oн9$6 Xe3=Rpyɜ<=Wqz]ws]umKXZhuƌs+O{&K^3ޥvaTǿb^vϷ]8ӫsլ Fqb2Ūۏ+ks +_c]ƴ֗B5/yʤ{o+(cXNP.?[`׌Hss;5CłNqAL_$ἣLJկTk;O+O_(z/sʽ/ Z̡r rlhtWssNc,Y뼾Y}C޶'.ZogJ>k]eWޔ/!mƮ| b32M[ժ-cԮ\utbo`6.\1g{#Òy ʽ~N3bR R,uJ?COoH>"~r֕XIuYocbgg<gֈvaix⇃ V LVjL2 +ݘꕌ{qs[Z%DG2Ϟb-?avzô4^e[~?ï k65Vm~n)v1^plÅ;~MNo-l5I +{!׌ :r̟>Nd~MnNyvm{K"^vkf$57qK[fϝ;N}RP|0LHJ{m +>hU^]ځEwZYOƮW;J$9}\LerΆq?Evzw~WS{{Ϛ~8WgN_%x+f?AN^3?9DcKݓҧqL<3beb?.f~>ܗ>zܰX>^,ͮ}|2呯N{7ۢ{HesTm)/Krc:sB{ӽ+c~y;d%gV +~UYi],~yfEi;f_ޜrYr?9nIQҢcò_|pYE %qwogޞqbFeal{Cyc?y=ꄮ<2Cwzr +[N}ᱭ&k.Q1i9GFy3S7w5ݙVkE\Wcy`钐HDM%>yHK +I:~X罌W9 +yw[9 D4Wn٥yW~Trdٹ8v>-S4혲l_M|zlN_R`C@RqEdfKn~jN;ÙF{W]QlŁFQ'%v3x<2՛B~M*Z~w +aۛ篢jǜ [cxx߫F K-V(JܼK[z:l5YCZMPpJ::MEU/q.+'Nٛ7O@M<ߜ_b:RtVUe/oa՚7nqoqHS5]J]鵏%O%PG)?崰I+`y6`\}M i-zs`SqG|ܛGUnMxPU]#{1C outtI6~(F|I 7Os4j^oZ삕Ӝޛ,h߹gGK}Pb\]6>^/{1mjpꛚ7jrźe #m=ZV'BZה ${GgIW5~;57WM:65P+,g穾/RR[>/`籓a',qao/x7i8ۊk۞ܝߴrA 5|s8%7:.rv۪|:DŌLֺ8{Sag%d7uf[̻$_/߽'=co?Yl\nׯ{t2E}ǭ:.Hmy5fq˨ c/Hw9>Xo;t= pM0k)΁ʷ7܈9zK]M{…븽fdw[civ\Yefƞ;j\mc=VʥVtԋ!~Kf8v״?ٻש(m&/cԕk;myc1{=x,x-Q}|S2oZn]hV),ls=/K{qIf=n?{@C^֯{&O F>./аT[efl*"̏N7<;/l>N^=+͂ybOޒ}\#ߝ]З b7znrhӗp28y‰ ++?N,4W\1/Յ2/7t1?ptiL}˯'2l`Ñ&%8+|/i n|7Ü_&۳s'SߺiA~(6;%ZM Bs2 +ʞwLW?ͩ/d<8Rw['ɩ +LBqTNG34} Qw_U'ɟ|cRHu;8w~OC5.1nygt?z5vzîo<{ݦOQխN%i|0:Naq__MRUF؂Q|2f'(ЙoY_07`Wo21w{h$o%nY\=N&̺"^/^( ;\*?%^-Y|nmT>x3|f3{=gOwG+Rw=C>J}=4GN[nzq3f;4l5WWEk׬;wiᥞ<ڽY.h fGg3|˕4(̛y [*KH1Cǎl 6-|QkdW:f23w r3ہY1~P- K;Ȕ.36/v˟PxpqP <[t +-,jeh,X҂M[)u^m1|]vἧK /|ip=s^$2˝OyTX6S3:ozR oۃ fEmOlvGG_+]tn>!_s+]]\w跪濿8׊>k pg̪UznOyqe^f}K ܒUawz鴧DNy?[.O7tWsS8):~LL};QxrcjZmK7Qc +`0γ[Z{6%45sRLSSoꦦh1hϭVMߋZ7-ybv-WwEq2+ב>(Q:ՐӿSJQNlg;[$Kޯ߶y[ρ|]&-=Nԋl^Jy7ff(pP2!ϻ]ba=>l,|anyJ"`Oio^= 1>ۗJ>V8,|S=jQ^L\+uڬr{YWIY܎Y\Q3٫ґG2\1s+^z3~4h2lº\$d6otힵj̷iŮD~Hj:%:2s]rg06~ ֜3Y"W}#] Ϟp%“VMڪ?}Uw9O}/M:up|l4Yi,.˟ɖ,6g؝j:QΗ|lF##敂ۺ6xEox#V~jg7LPu[wqOnߔhb`R.]O0W[v{,uqm5 Ӄ){wL9pn+7ٲ_NM^\kg6' +~Uq1bUK{ENm|{JT+mѶxQ:= gOͣXYy\'^u7 qtZvK?y!GNyT3+G:ԋN#8zoU_<8UGE +70!vhtKm,*kw[bd؉ozv:= _(ug݅R9Gͬ~})lje)jL>eݖoޛ0`eF}ٿw4]fj}c89*-]1u-/H~kv<<$eIũE ۿ<}vJE}?&Q.>¶FKzeC2>-Qk9$r<Q٧װoǥ!ܭ9a&+O)+KWWhgz"eWʹždevd/R=}۸,{gKW\^%(ˍxmsoj,x[}?dfCϪh6Hb{5,/^3b׾++H;FY'y^|e˯k/e )oyM?}+8wysWO׮=9ҫkڔW~ Oߊi$}x}ml7ſ8V,ݺ\*] Is]}C꽻&nzpĢ%jreOF˧S˜l׭xGՋ j+<=U} obݗ-oux}R{~~_W4çIW&OpZff'wPu6 y'j+loV}&߾'>l*?#庫m|:rW(WkuYv?噚N+;,V'\9ʆ $.Lo;kGg["fOl7~`Kѵ$NXln'_5Wnz.6[sNU͖?6aN֕ٳʦ]]5CHnܽr|xB4U[}ZedҴA >`,̅2=n۞*q)*%$~_[yۀnJvfux}{,+~?yM.l>{H;l y.|i2{5fYқв腩;m[au;qߙs;m]㥻E$MTӰ1-Bt\^m'w_{3vwun}ӻӶԈi_%r8pqEZ绊,nتK=W%k؃ rq} Kw֖k,YX$UK7w冀$验C/$y)א[ewk(51wn }tYMx?yOLB-SsWgl[4&󯝿 +%HMzr~Eƥ|~Y3޼ƛY] +l_ߤ;s\{%X?;{>Ee}I +Irn;ڵ~)Of|귝|lK6`%wxXc+A N)c8=wFow*<2gCeV1gduyw%!wLXjtGZx01i?k_\%QA=?X6˻e- W|I-F9vhmhZzIJ>v+W8o)vf|=G~ld^沋fW \οb2&%~ugtߦ~ݹj7s9o Kw57p UjnnZ.6K-뷶=k +- ٲUgk2,{\\';ϙKK$&<ˤ[Eo-tjZ̦"nFW.rSUaozR};pɑ bVOt:Bab#[զ/|⭵h1zuIJ kòMb۳Fmj&U;[v(x$Ikm_xs |S/(n)%.+{` 6̷YgD3|YԾ$E'~gxwz!wU"[rr[+:v$&=S +_p^}1~k%z7wn轾`]5J؞m}a敋dd600lCҒfSW.c*a3\߾VQ)9<_y9R#]rd"ٯ?:(=乊tPK?A CvǬb,`s_} ג%-P*9kɉw9QQ V!8"ˠǩOdl}HWN{b 4lU̩y}̸5^VkWwY$~I+u/:JX0т+VN_܉4c~{\7近)7@'~O+sfQJbUYTR\%eVܢkmf6TE=˲uYyR eo,ĺCw`>NZݽ#8L):$ʪ<[盩 A/MV=,=],lkk} 7Eͼ~K•ũ<|d|lea -3TT#_,SIWhlWW3t䴥Y=AFZ.?܌oX|_kAꊈﻘ]ӳ}tc鳓Ģ^woAy=Kܫ=5.4[qƪ_b[3 [p,?~s,a;s]b|#>\~~= >Gl~iy!RNJuM\a9~ɿ +柟>fxW*'_/j${ris]?ɄHwZ7J?c{`iK:U#RvQUw:N[ZYW !]bA[]Ư&[?KEl2{bQ =N>vkhY%%D- oݣzV==R_SeOYE=4.Lκ Lۗd%wkJ"2%|SsB{.WP'ӈL@m7*~=¹?҇kByj.m zFl7?Paۣ>l?ŷ~AvJ _؅4y/*d\1>,n-Mɠ NҷIrOfZ7K5ݢՌo͘7kMMW6^WTOc+?ʵi3b<6aJB) X|>y'sLrb{67Ķ%j~ÿg\61_ g +lVQWd_)S19dq3bGg82ݭUOwwtZbvp*tCb[.%oZ^+ 23ܑ*e^~rLb&ƌ]bY}za$ul_"ǣ)9sk)V?wxQʼg-N9>y6}Yc 3Y?qM6{wVmZ?q )-Y^J{FU?r^P\o{IDaFJP/)Қ=ѩ3?jυ-蝛&`Š_[װñWOۚ /aC idMy,JTcޢm)eJj_oezk&\3Jr\ٕ$~S Sr?NzDOS᥷nRmv}Ls/wOջ+̟mc1o&zkKgڞirb񮛹Sh1+K.3ic[$<~qJe?QS&+.uȊt=G@c7TKloYmm%=?,Ӎ.yyϦ/gڡZGzc}M˿$?%N-ڲ﷭fx㡓vN"߼)Rf[f}ȞԮ(s2wqx]u3BTK*c<5)]mmS~1y$G:_|s*XXc3@ʯ,)}dZ<0hzgԙs}$:,Ci/So1`3"s#|fјrkIq=3V;D7ŭK.LxpqxpIlWpou SLϯ 9>uM6Gヶʰ3M*L`\ ?+.0s9r+b/dD_8cU˿J o.?ETC%Wq2Elhy#_8oy$Bǎ\fjG=5Fr ᡵMufTRM|d=xoifN<\`[ܷ.W^:ffJz}?52wwn`Z{űK0&^rYe:Ι .D}F;;vߗx<&vG>u֬k9zጞ6'9}(/lw [|f4.Q] Ʈ_/[9abdz a|mfpu^bxB-/ +[nLA,tX,t>QJ_ӗ[}HйB- cz:.5sLS8É;je0gu}$?h*=_+gX(aȞB޷.f+(oY</z ~^Wvju^b}ʟz>{}L}`Le/j01ǿ)9},=qx^y oi9zuoqߪ\8s^OX1P9~*k}ruכn\s}tMmwvynߴl}2'zjg䫇fK~My2Wl 7dKrU_wJer:λMQvwVCw3nOtoY'~,z"deCņ^i<˒;<%T'Vlx=jG5}>bC?PKg.lDk#"vs͜cv]賊/N ۛW{|A~3O 3qN :J'jXr̢笘tקϳΚmǣ^gm_ivשS:^gyTW냒( {^&V&M5hJ&<Tu2]4ߌÅ G~G͹=`㢭r+ ^hjZϭ.P{ێzO$O\ոio/ǃ홅{O43#I2}>U +.GQH=M-Ӧh޹ȷlH#mG')-9}] 8qw>^׍e>:4?v`*v M'G,.M>2 + fL%Ӈ$ /2m]Xs/RGmO'Yh~Ԥ[^;LeuNLaΙ O^yޚU)8yDbw3*u]ӊ"=Xfe + zo&hNZÛ)4jn3rݶ)4!S[+xV=!$Y:@_ofΫiTJ=b>(qej7+_Zv6ӷ<[쭜332$}f~ݼO 7 +ˮcy8!e\YR&]@+|߱f+3UZ1|>k y|ͅ:֋\Cźm[%YL81#p=6f wV:S .tm|'#}<[s>:dž\|֣e;{To. yպCK:Ua!?e_ſLsئ>k&BD]%Zu]w&i?4d\ufg*a>g1J Nzc0v-b/}hꨧgҽ>{r*a_1Ua*ǮMR{i%ZV>ǟe>Jtn? idJm"˞R[eu3{n>̧y}zퟸ>jwmHQB8;n}]nΐO9dζGWyz|Iu)ƌgM=-VBIk:O{{wiTkg?MSG^Y{㼏p-n`O>l%?=39GN凐b9nmb5N՜x1o*'Ys*d~i \opj;FAg'lH:~ qIF|4^Mڳ8 vqFV0:ŀ׾gs$']u4k;G<^0s<[Zgr\“9]LXw2m9{٭7n]{W4qX/ гY Afwޠq m_W8iqJf$=!7OKbo`ѲW^p}>?\| ؍6gRozpZEX6~|2/AMNm(_ac6Y8nEʳۦ7mLC(ސt73Uщ`1SnNS.IRjO~|; %IH=buE\x 4ڏ5)mh_&ǯne4+EDf]Vڍ#O:&YReT8%vb</,v]z&i c~ؘ+Us78OԳ<ß ]$u迎k.׎VVK֕[Lw}m'Uܿ&}}fksv7oн5!F?.kn\$7[-D: OugIC9loe} &?+{8f2sMJсQq'{xO<7k.rIUvN%ߴN8``٣_~ݭ.,3⯜Hi4~~'|"OVl6kIܕ|rޡv=js>@k^Rr~d0%92zv_H=­{>'bV-,2,wÑO'n\fӾ/WI,˺ŴGw%ה KJxRh='h֌Nj>諵*}c|es'|sz\~ub,.?ᤰZ Cgr=gO_y$ۛLt1 וYa J͏~M2o`Py1ݙ{՛ǓΕ9ڮ]'UxOĶsg-_YlClzOxv"*֗+*Z̵\-\YJzlҤ西6Zt"n+džfUO+?|V9un<Imz/Sը6& ;#,U?e8k_,kƚS>zֿIV}ۓ.&Sfp|*[rkI/k:NuUyou^6pQ%z3_`׻p7=+6Nxɐi-wzV1)tR}IoT&DG(g\idV4y)Rr)Z0nUߓ(؜ǯL1zuz~]5IGX.L:W 4;ᄜ%BW?V{w[h繭;—iL%t~\bnƛ&dne@w>& oOvd߰OƑ8X.-xPvvG>]6 3{qX-?$evgM8\eQk[l:zr<|i]f_X/VFͷ\K::#/~X#ֽs~K|P z{ړ%sI4*lLT^#5B5Vf]i t]|,-Ww]znʴ[pwO#GM}l-Δ|+1So9syI&*(~~+-&~ޭ5oIg rѧEfGfH:xYݣ==T\f+sӄ|K\NIp.~rQ,b۾ aIc}z_w1zo{޹/ +zlSbؖKwXV֯#8ӯ1{ų6oJhsWv;xNcXEZ1 -Xs*lccirֲN8'HlVEթ o׸ǎjѼ%}ϼZPsWNSm'm)M7YqԿAٜ+OFt{ +;Şi|WofuckL_sMJZ6)U5HUFYkoza?ɟᶊhwPe\.j˞~]8tC5/*6gMN?饜ڏ oMqЬUbO&r-ܿ| S]N;k ןMאݘ*|ͅs.?~?GUy+7hu O^ZGmۋ'>]!ꚠUs7!U8[Gv.Xt'yƓsx5tfLgϚwJ@3x鍑bur,:o|!ASVL|+!Zc~:ZM6u,۝9ӵ:|Xè}|opo^:BgXySNX\];e;HE7]p,y7䘦9w,{ mo&ǰ?bsSk'~=y/0[Ndᥚ-k!vq=-ߌ>;пU)@Uc3{r`Ӭ]O&_r_N-擴Ty +|H=>:4NKȻi]5)Szd+ֿj<.sgﯩD3O{ߋtE Z7 |`R^EmV;o3Ț355h עkw>{@KD fi,8d)Լ:qzK&Y,~w Ӯ7nt:в0KdҌ5OLU osf-3_d){y9d Lv'V\;;{؏?6,!JMtt9G}t3pKr[lk鯉^g{yu}yAVmPnV)O$fj1EKV;XfZ[oɰKוFxs\ݮj׬7u®L*$q /RB7=y; W:j%{Nܾ-hgkq΅9zfްsxyj.9qU +gw3׼tEMFv!y.,7mW۫G4䧙 l iDij/i֍Sofܡ23_9d:GJ&'zyZmI*aH{Vnچ+5ł6qٻg#d^m6wy[N"Rҥ/59O6~j{FPY޳Efo:T0ΑE l0Ҳ~dd6yޱI~nysX>'GU5ӷUTy. N ?[$Srkfaq9$N;9 ^ܾg۟k9>uChk+fͻw8\ZOvNe<\VѦgwh/>?,W]Ch)C+fZkZ>K䖼-&Z2qǵWj =U +0-7kSS4 +̒V:)#IӧydՖ,O5&{YseTp|Sz,זg)~=^\sɉ=E2[伓0\p#7ٿdݕc;zKuUou,i| ue_u^͵{qǟߗ"n]Iua֛-,]*V /|"p3Nmcprnp>QYFq1{dO]>FW٪M?؏T+,(8nP$&U؇1~x2U^a]egu׃b7?.s̭e6([{~i՚Ij#ޯ<Ҽe苅NV3w|Xۧo2ڒ+ukٌn~/>vi\ㆹLa(s9.}ܮQ@b'{f^i +He_nnwNMcμd{m]{w~{.qN3v{lz=_u|yknxN[ȗvvpcE/o8*Z%wᜲ;6>vFo{L[EY O-hIP׺՝]$|}dɪ)|ُ"/Xe7l̨<Ğ佌!9-f3&9l:Ża6j5Or)Ose[K{#9vq~Yp +yoH>"!S=kfEW WKǿ߾uSv-?#;utO +_rmyĚ~ex"!y]=b^zn|Gy3=[||{oպ'uE}HAnr Z.VR]۷ukl\con5|*x[Zϖ%| Kƺi}f_zצ4Ὃx:ϥQ8sz~뙙+yݑ[i[z_mk+_1~_uOE⵼+V Jʯvc}:4ljZ*\wߦFnG:eٱw/?[䐂?BsuxU;ޣzJ?T3-Ev,˰Ysm=&X-VRV;3<#?7G{{-\" _O<7O3׻W߶T{jks_ԫ_ſ*b4..]i+;egnRx>Ϳyu7ElXѿ aWxޣAM~7͹=pC=+'w-hHص}6!gz3/s2D3-~).uq}I bgpΚ¸]?6{Y~t=Ǔ dFmf +5'^=}TL1ٵwf(|_O^qdG;mʞϳF.)`mümv֥oXh#-'|پMJMHzuͩ7w 'Ĭʞ8m@N綰`^Z.7߻־e?&*i5& +@D1Ų'{ݬJL]vlW;S_Ƽ#\n=4]:3oq@E +nz!3]zŮ&RU;bu^gwnyʊr?]8ɂlW+JO|l5!ԡ_a%[E)~z㥝/kD7|*?Ş=b^ܸ?[=s;1iu೚yG^wmזfY{f_ƕKֳѳ^-`W/?|D= $=mI]msC̺P%6MK;ApD|q̞ie-[z,%?}sb}ߦS^Z_fNl޷!za.ƻUli ڕie۵Y^[0)M*~Z2uS5H`[wIy\/n?G}0~AZ#ds]̸*⪥AM/,XXE{^[WjmQNǖ&^'vG:ƾIuu,E=b`˞}bw +^!zn55?O%!!cQqd ̜s8Wb.=w<]sIR+SDՔT)8pH3bي'p;x{%ir^VpY l .Wo&'\ݝouLNVV.'Z^mbN_e^Yn#bvi t!P_:v;^yt2;$eeݗVwsHSf5{h2(.`ڨs%I}[n!W`/v+z_0д]$SYfwZvv1}k%9ϩ)B{uL +?p̷.e+;i\+eRf%JQUI2^L,ΞNթd5{?sv|Y 5,vu{c-%N箯j$إ+^ۄzOxq시Zܧ,*:TI՚e^)\y~?b&Ezm;GeΕ+K䜻~_3'+m[r_.{/]i((]Μ\桷;|7?y7d ^}ϟݠd,sC[ܷgxx?o55SɞrívjV9nxfd?:P٤ʬ;VM.] Ongt6lLǽ|s-m1+м|gΊ:-yLҶו`;W'Q u! \(jms%b"^E{Y&hVo;H\ϻ?4S8Nkj^UviN LQXn+=@/@Vh21+) Ghhhhhhhhhhhhhhhhhhhhhhhhhhhhhh                                                               Q0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0 +FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4Fhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh(                                                               !0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh                                                               Q0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0 +FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4Fhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh(                                                               !0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhxc%?Ӵ3efx0X<,%000D@{˪ : ?xZͿգ݄000~;'ss״? wN4^PWåA7 +b&9d920A P=0 C-DHD d&^^IjE O/ + z)% A&*Hi;00+JOf U +΋<:OxX~/q gh~Z3*Fm^Ls|(yu={X+sb.=z]=vApcF㸋 +HEGs"~|p牖%L:lxdOK% 6 %\=xa hxɳGSE:8<0t007ڨ240{xg@l[.% + ͆uo+P^yѧ]"ا;\Cn~O. .,.5O[~.gqw[gxNÓJ<;{t&£DE3Dţţ\EŠݡFŀEڣ;DE;FE۝EECGg2.*5*, 6_2[ +`nwm'wQ_znrpNnNnNm.*.;:]~r6&Cvxt,p~ѣ]G%$ nҝ⢜x){o +/m5 yӱ]q|xC.'\;/:|¿As 8|{70108jQ1p<Ցw +KKg(CM +Oo9*6.g];oQ9U /;vǨX9vjA<ߖ?$];Ou{?RkVWS.'4ou2th>(xҷWߑ +( AYb|G7;yT<{~RR;eT|{S%H>5޽s΅ (eC(iÅk)ǃ]_vPY9S̵/mOӮ۵]8ɂ c.W]O|ȿ2QXŊ eW%+h򗴫ǢY_\KT,{ex:cTlp1304fv .cqwx1caΓ>7=O0t߮"  &u:%ڗMwl~ Tvkw֓.@!j!e P\86d_ | <Y4_;vJsF3/ןȡڥ"ItKܕ!tK@1!Fppl~󒏑ѱA;CehyXVJP *\}Tl@U( =4?r/@uayڥ#MOuc +MO>*cM͛'AB<򎚟ze8}&vХM;oztp8u2x?Сc"QjxA'Kz-còDE2DŃ}qkMnn"pOKgG{@K{D{H)O; +K9s']gPEE]X|t7(kdd`o kB5#ѱ1qCw|zyMۼ\#|/?vqU5(:29oj7ʥ\ Xo9<.=%|:h<\vKGpÅ%nW.{m8\o35PrTX¿bvG^sBy(}Y oQ<:oB<Xbb]Pi #yG!Z'RgV3=J6%'L _8yW[^(Wd灩/ >6':B`a``.$%MCxFip'b._ۆ'={ < f!ޘxp +^K n&5:O+vjH(C\-y݆t~],i߮*s5MP3l4yړ3v(]<  8Sppx~pQ j$?٥1@f ?/l[.L{0bj ?P#ZҀR 310x*x00Hoh>b!B<;π@c'<;zwvаO/ P2Hԃn>r+·Ѡza{# +'0+@vh([߳Oa@V0X +dt@Rdڿ}-ߔHx4)q`Cܢ ,r1ܣ5W:٣ .*itQQ 8\2004 *;{v{ j#d<;8ocyP~rFVݠ +̱;'Σۮo;cG}(o;#ᢢxGqЕk ޽&.5*/VRJGwػ[x2008tը8thsQIf $|եs +h(%:t$tTt.Q {oQx +h /1 {D)=Dw PnQI1Dٵ1(F!70z?]\[pC`5/mkR +6oeb`h=E$!3@ݢCT9 Ҏ0x?iyGoJO3pe j|ޣEe٢߫[T@[<4<+^pc_r!%]L q5`a^ +rK+kP[th( +e5C&>,Νj}u^97DEç/AZK=[Ѽhy(ץAK$(w+yسKʼnԣ ztdxtרQh} w]v(s{z-p{}v/h1#":.\ i݌=:O{4Qh=Y +*~00 z00xԠgчC<:{t^h~b?8y׏ã`7Gs@l˿<Ŀ>l _y0y(.>.HC<; + `]W!~U?@2H"p9(yÝ:OGD[ ̠ʺq\"S&1Iwf`إA`?nxRGn>pZi>wP +h<3CC) [ o ^fH% Pptt5<4^[BF`5v1/4 4`A4vr`1(1o*on`f`h"%Ggp030xtytq030y"Jj@AM$ixt֨(PQ9|]GRo`KK8(Mt>vy{:% vOS@)v`yv~PοȻ 7z*~k7ooCr~1򷫁 lg<ϱ͇d*X@].*]T +@ƃ1j\k;F5g!!1{ѥ_yn};*_e\ +U%Y/}:n]ՠjoH<j_.%ݽ7mBbDe + %,* yh˨T*>7?f,8 +Jݠ\ OBr)q(N)Me]WA*(xN +σ/X#>c__$8Ƣ'=-E ۡ5;m<:x$l`<+({RaVPs؃a$u؃UDBi@(e@{z@x`O/+[]ܠɖEC=:?0cnr!na ǁWlnAaU]aך1:xts3^dyÁw̜w8Wps(tfs٣(V\b?glF^.`d`rj~nRq9.g`C!^yw +K2`/Az\û;Ԭ۹B?-'KU=<5<=X<5X<;gf ՠH5c?dy- U! J򡛁G\$yvJ!fPvL qoBL\χxv1،բP SLS|ɠ윢r.Paw+KB=;Z_<:>_lRF$ȟ"}B. +Zo +rCL% XJ}@]g= wKh3<ݐRs +`m9La-_5 ƗЊǣ\ `j~z@6Pw_!]_MQn+Q u ,<:zt34tc4Lfvl3(ErGw(ñf`GdPNW,E0 Av100{t{t +^`@ K .&R.'F 6[%m[@mr] 6%/@Slۿ R,M?0m򉁁U&@&" T.5x@ЄA6u.7^!Yw(dž*f' [kA ')!k&Pk~C;pk0l'c1*!*rdzGo+:o: kΗ/&}߳猨:TZ><:H}FΛ|:_o7d<˷s/Y/}<: ^<}D̞3a`xs@-}:tGdv+^ /<̈́a8yAqh} H$AVIK3Ptt,ڇX)ACZTZ';j`񼶇ɂtz ]r(Y <$ĿZ4,P}۸9Oh^hSw96cONA8t0| Rρqo@GGG4+{peb`x- +dT +o +:^P~{/p(rtg|"DLjB7Ȅ @5$׬ 'p 6Ć/N)MxH9u P߲ u +F- /P-1hR +{j[Wo>1*m.*ݠ˝ qWo`y۠I" +^,W}>*.*N:oӲ̱R֓ HW2(hcOI <]?tl|xn +Z|ZeCyE 6f| a0L0X^C/8w= u@2.* + ^j@eX@[# γe7P'<2[nhP$Z{hJ5*/|@E| /A# + Ӳyo?ȿ͋D "@'100 +)9*~PyM(.lFc@ +Z[uF VΛAX Av!YlˑŘT*O{6Vo`a`;-˚a.34ghx%Pfp5| m>z ?1*֔$|b +j< ze# +-J$A /BA fA> +g;?o{_ +go +Go+.vxr6wc6{$U|\"^G; 9.^`zX^( +pt)&(#9|;x2ubh~@Q)Qmbypj%^|Ƀ" +!$|z3=q +j<<ȿ͗D:y>/<,:v2g4Jx6eq5<cwm=PrDУWTA ojk 5Vd`xQq +*d``xcTqCGP򂅁$ WGjmQ.~??X&îLP{D PsV +<߁([r!:p)}iP&HeJhahyOwPq^G4zRԣWt&e- w1_TYe]]:(L|:: +NA\}`&b>@Y[ YpYe eZ'8бhE,/2VGˁM*МGoJOJGMPLvp/r@k_/-yۓ%h!(x +0tǨx6<@k o7> 6.* !* +j @k"X002zZkh+3ҫbAz=]T<@QXxPHAB khG r *$5^| +ahFjq[ !Tg`x1`Aj]R ??6xA +QIv/^Mn^Pisc8hrWTzmH1 +mN=భ6'8/ز0Arj&@]kaee.f`xw Y*Dt:ԳT8alxۣ8nrT <:d9=`ڧh%fSDtЪ^ Y%N e"vA\Pït4`<]"y +]. .y?G@x6?jI>))pfQI*vbAYb_0k4۰R4&3h)9O5cY8Qcgݐo?A3P à5o^[Tc!,>@#(=<| Sy5Gzn kŋA"NPAsDAM7 +"Pڿ_?ܧG}5(a=hw~@ РltPr5ŪIP# e-QyQ\bUf ښ` +Cn)[^(105ר0v8Vw5>^$P >Lk5Qy vÎ;@'@vkxvB,=߀)ceaPɣE47ۢrToÁƔ<:^7 vt75(}|@@P?Χ7G% ΢``x|~F7P 310sz-c`.x*AաA&c`x5 bvz$yt\Ё\%is&qPR5ARK@Zx|XRjkؼ:kV qΛvVm{ix V~htdrP^E hD7hރl()H)uA .a"ȕMe.*ݠo.* vHJ69*E[s@b>)*v-ߎ07atzqͧl8e/`,Uwjey.坐4**+<]T +<x4!^>߻G ;JS؅ۃ6wzgx`Ofww:6wz7hDB,9Gۣu:_7^^9ШãRw\:^~VI@Σ[أ7 4Js<z08K&σ/2+懌>*1:6?`8 "hZPx%+gy懌@:4 8X >< + nN>Ȫn6Uǐh7u@J׉)00oCǎRY\&T.3*ˊeC岣r9P\.T.7*ˋCrP\!T0*W+C劣r%P\)T4*W+ʕCʣrA _iO>Fh==81037QhQo+D{4> +Ŝyx@j`KfC=:f1d1v v r t _)jU!F@ρ=/<:}9JxgQIQ5@[t:cT8R,إN3_¯p _/Wzp#_BGs-l~7/+W<0<߀Gsu +xtr@D |rGg<51W dsD+]W …_@+h/ADDDD߁ +q s] "###'΋| +4yP"o0OQy fۿb V +\ N>~ YyٙyEɩ)FEI9)`nqYnZ@v~pj2&f%3h楗d(*j**hTP]PO?MҴ" +ᛒ +rOfRQbQSbqojn~QOfRPjApI~pjojnxQbAAjntI-.K,ϣs *)rop~iQr*-ꓙ_ZRPZIAVAC,?3EAKS(O)AXD\܂bsK3SRSSAZQRf%3x@%0ZY♗皓WR_ZdlYR`k`PS@X!>!X M /S/=#9I.8,ձ(5Q/ +z# RA ?aG%{$3wb +;8{Wt'v;=*9g? %$zဥd HuOKsO-q+) +adKVߔT?(_ rZ άJĒ HŮKJ2JK.azl4L,4lJsrK2xxB饙)vPvIfnvtQV,~ ϼԢP_X <Լ` :x̊'PX[ Ӕ5a5 5T ,*tU LQa8ȘA(EJ((V dT3w3i>3WyXDǐB_U_|s#T oݙ ͞xW7xנ Ēb["M.E M`Wg+`cT.?PQH/AN&S~~[q -BrRJ2RC=]RR2RS!2P*@PijKfܠ=#y=\9*}D+A@۠BB`$jDU隗b m Bš6V{~ckQQ~BJ)`{! +))\H>G^[L zc#M  P +rvuputq |^Qp+6>45u@6UTX +M1bh N86Pf溕PY78[. * i05% + +) +y% +e Ĕ"Ē"̘ppg e`*Awuw+ҩ-ƝR2sS 8=pqOދJ-G#CઙHPy @8SS<4@\SA5A/_!ISAAؠV,@GѰ h*L傘휘^)^!6d楁JjP_б 3doq)* vhjZsA)z)DBd'ᘒ()Lqf>V +nT`b30`yyy +% +NE) +.eɩ +.V + u(o"crAfHfnj,s`zkHh$-Jp<afl4QXZ + NM)%E%%%༠ + +M.ܠ"c pP{`')53$5 (1IAGjp *aN /Os.-*J+{4ZkSs9 J % @ jx  s}3Ӌ8b6iVGy.)I@%BkErjQW|wjs@hPtQ[T@'pg$ehSiZ"BAD8 28LGXV0y(QpF8å#P#: +A.CdNCP'.p\ A +((<PU3>$8ATԁ (J-N+aPh&CHewԼԢPCs@n5t}A +n +n9%ybX ::+*8PuHMfP&&gdB"@뢐3 a ,*)Mɬ(eg+J]0a +y@31( r⒢"zZ[P$ Lc4ztutm>&wnȟW#(J3YBBi#( t +(}JYA{BPJB4( G,h555~( N2inޝS?/7aj`4hfh{5Ûjm09M/]dp +rpu哕W2\J*U1WU\5cUV]ueUV1X-ZojѫVWX=}[W]s9eC  aՂU+VmXcՁU'V]XucՃU/V}Xcj%V+Xmbj#V'X]bu^, ̐ʐːȐ:wAAt*~C                                Q0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0 +FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4FC`4Fhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh(                                                               !0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0!0#+HWormM3z񽟳t#G+I(Hae4< `ȸBiOO +.G3M;Ko6Vȴֽ\zBTaï9w߿:\`x^狴XE֯Z5`/U!BɫnƇgexXR/cXZ7hU˿=†pu+C\ \ No newline at end of file diff --git a/OVMFbin/git folder/objects/91/983738fd10bb072d2f624e2dba29b4f14ad6da b/OVMFbin/git folder/objects/91/983738fd10bb072d2f624e2dba29b4f14ad6da new file mode 100644 index 0000000..489d7fc Binary files /dev/null and b/OVMFbin/git folder/objects/91/983738fd10bb072d2f624e2dba29b4f14ad6da differ diff --git a/OVMFbin/git folder/objects/96/1da169a309a0da546e75e6815df5958ed233e0 b/OVMFbin/git folder/objects/96/1da169a309a0da546e75e6815df5958ed233e0 new file mode 100644 index 0000000..dc941f9 Binary files /dev/null and b/OVMFbin/git folder/objects/96/1da169a309a0da546e75e6815df5958ed233e0 differ diff --git a/OVMFbin/git folder/objects/a3/c90a67ae89a7f7348529487e4b2ca4132fadbb b/OVMFbin/git folder/objects/a3/c90a67ae89a7f7348529487e4b2ca4132fadbb new file mode 100644 index 0000000..1d95695 Binary files /dev/null and b/OVMFbin/git folder/objects/a3/c90a67ae89a7f7348529487e4b2ca4132fadbb differ diff --git a/OVMFbin/git folder/objects/b4/faf65fc21e7a7a29aa8c8233191a1b5a1af644 b/OVMFbin/git folder/objects/b4/faf65fc21e7a7a29aa8c8233191a1b5a1af644 new file mode 100644 index 0000000..8896681 Binary files /dev/null and b/OVMFbin/git folder/objects/b4/faf65fc21e7a7a29aa8c8233191a1b5a1af644 differ diff --git a/OVMFbin/git folder/objects/b6/62e9d6d4df2506f632c27dae7876ddf6dbbcca b/OVMFbin/git folder/objects/b6/62e9d6d4df2506f632c27dae7876ddf6dbbcca new file mode 100644 index 0000000..8d7076e Binary files /dev/null and b/OVMFbin/git folder/objects/b6/62e9d6d4df2506f632c27dae7876ddf6dbbcca differ diff --git a/OVMFbin/git folder/objects/ba/fde5bcaaf58e36c4bc2e3542fd88522aac8c92 b/OVMFbin/git folder/objects/ba/fde5bcaaf58e36c4bc2e3542fd88522aac8c92 new file mode 100644 index 0000000..cd6195a Binary files /dev/null and b/OVMFbin/git folder/objects/ba/fde5bcaaf58e36c4bc2e3542fd88522aac8c92 differ diff --git a/OVMFbin/git folder/objects/c5/79e7f5f6c8cace8da84734d1fdbc067bad8410 b/OVMFbin/git folder/objects/c5/79e7f5f6c8cace8da84734d1fdbc067bad8410 new file mode 100644 index 0000000..06ac4d2 Binary files /dev/null and b/OVMFbin/git folder/objects/c5/79e7f5f6c8cace8da84734d1fdbc067bad8410 differ diff --git a/OVMFbin/git folder/objects/c6/3c1e90b9d0bd5127d5e499e8a467050e11e4ee b/OVMFbin/git folder/objects/c6/3c1e90b9d0bd5127d5e499e8a467050e11e4ee new file mode 100644 index 0000000..484f468 Binary files /dev/null and b/OVMFbin/git folder/objects/c6/3c1e90b9d0bd5127d5e499e8a467050e11e4ee differ diff --git a/OVMFbin/git folder/objects/d4/e41edc2cd1c9bd6599bc8cbecff4bdbe9c583b b/OVMFbin/git folder/objects/d4/e41edc2cd1c9bd6599bc8cbecff4bdbe9c583b new file mode 100644 index 0000000..39ded4e Binary files /dev/null and b/OVMFbin/git folder/objects/d4/e41edc2cd1c9bd6599bc8cbecff4bdbe9c583b differ diff --git a/OVMFbin/git folder/objects/ed/cf988ebdfe5096fa375ba9e8a7a0a73c56d7ea b/OVMFbin/git folder/objects/ed/cf988ebdfe5096fa375ba9e8a7a0a73c56d7ea new file mode 100644 index 0000000..afcabba Binary files /dev/null and b/OVMFbin/git folder/objects/ed/cf988ebdfe5096fa375ba9e8a7a0a73c56d7ea differ diff --git a/OVMFbin/git folder/objects/f1/87318260a6698bba1bdb530f67610d8ad68ab7 b/OVMFbin/git folder/objects/f1/87318260a6698bba1bdb530f67610d8ad68ab7 new file mode 100644 index 0000000..8b2f9a8 Binary files /dev/null and b/OVMFbin/git folder/objects/f1/87318260a6698bba1bdb530f67610d8ad68ab7 differ diff --git a/OVMFbin/git folder/objects/f3/27b7a4d421c9277b88686b70eed986c75d6ddf b/OVMFbin/git folder/objects/f3/27b7a4d421c9277b88686b70eed986c75d6ddf new file mode 100644 index 0000000..889acf9 Binary files /dev/null and b/OVMFbin/git folder/objects/f3/27b7a4d421c9277b88686b70eed986c75d6ddf differ diff --git a/OVMFbin/git folder/objects/fc/f48c7fcd85ebdc38c9cb1fd8f83bafd8f3b932 b/OVMFbin/git folder/objects/fc/f48c7fcd85ebdc38c9cb1fd8f83bafd8f3b932 new file mode 100644 index 0000000..d99b221 Binary files /dev/null and b/OVMFbin/git folder/objects/fc/f48c7fcd85ebdc38c9cb1fd8f83bafd8f3b932 differ diff --git a/OVMFbin/git folder/objects/pack/pack-18e7b099ab194dd8c63533ad444da7a9532400a3.idx b/OVMFbin/git folder/objects/pack/pack-18e7b099ab194dd8c63533ad444da7a9532400a3.idx new file mode 100644 index 0000000..d36d942 Binary files /dev/null and b/OVMFbin/git folder/objects/pack/pack-18e7b099ab194dd8c63533ad444da7a9532400a3.idx differ diff --git a/OVMFbin/git folder/objects/pack/pack-18e7b099ab194dd8c63533ad444da7a9532400a3.pack b/OVMFbin/git folder/objects/pack/pack-18e7b099ab194dd8c63533ad444da7a9532400a3.pack new file mode 100644 index 0000000..b077e73 Binary files /dev/null and b/OVMFbin/git folder/objects/pack/pack-18e7b099ab194dd8c63533ad444da7a9532400a3.pack differ diff --git a/OVMFbin/git folder/objects/pack/pack-18e7b099ab194dd8c63533ad444da7a9532400a3.rev b/OVMFbin/git folder/objects/pack/pack-18e7b099ab194dd8c63533ad444da7a9532400a3.rev new file mode 100644 index 0000000..eedbd4b Binary files /dev/null and b/OVMFbin/git folder/objects/pack/pack-18e7b099ab194dd8c63533ad444da7a9532400a3.rev differ diff --git a/OVMFbin/git folder/packed-refs b/OVMFbin/git folder/packed-refs new file mode 100644 index 0000000..250f187 --- /dev/null +++ b/OVMFbin/git folder/packed-refs @@ -0,0 +1 @@ +# pack-refs with: peeled fully-peeled sorted diff --git a/OVMFbin/git folder/refs/heads/main b/OVMFbin/git folder/refs/heads/main new file mode 100644 index 0000000..417f33f --- /dev/null +++ b/OVMFbin/git folder/refs/heads/main @@ -0,0 +1 @@ +961da169a309a0da546e75e6815df5958ed233e0 diff --git a/OVMFbin/git folder/refs/remotes/origin/HEAD b/OVMFbin/git folder/refs/remotes/origin/HEAD new file mode 100644 index 0000000..4b0a875 --- /dev/null +++ b/OVMFbin/git folder/refs/remotes/origin/HEAD @@ -0,0 +1 @@ +ref: refs/remotes/origin/main diff --git a/OVMFbin/git folder/refs/remotes/origin/main b/OVMFbin/git folder/refs/remotes/origin/main new file mode 100644 index 0000000..417f33f --- /dev/null +++ b/OVMFbin/git folder/refs/remotes/origin/main @@ -0,0 +1 @@ +961da169a309a0da546e75e6815df5958ed233e0 diff --git a/OVMFbin/git folder/refs/remotes/upstream/HEAD b/OVMFbin/git folder/refs/remotes/upstream/HEAD new file mode 100644 index 0000000..abc5c6f --- /dev/null +++ b/OVMFbin/git folder/refs/remotes/upstream/HEAD @@ -0,0 +1 @@ +ref: refs/remotes/upstream/main diff --git a/OVMFbin/git folder/refs/remotes/upstream/main b/OVMFbin/git folder/refs/remotes/upstream/main new file mode 100644 index 0000000..b41822e --- /dev/null +++ b/OVMFbin/git folder/refs/remotes/upstream/main @@ -0,0 +1 @@ +6785366a291c513f51595e631c52e9ec176a2d74 diff --git a/gnu-efi/ChangeLog b/gnu-efi/ChangeLog new file mode 100644 index 0000000..b30ba25 --- /dev/null +++ b/gnu-efi/ChangeLog @@ -0,0 +1,1324 @@ + Updated Changelog + + Signed-off-by: Nigel Croxon + +commit 37d7bee82a627999563069b090866076e055a871 +Author: Nigel Croxon +Date: Thu May 14 12:38:39 2015 -0400 + + Added some missing error code descriptions + + Signed-off-by: Peter Jones + Signed-off-by: Nigel Croxon + +commit dae0b4b0b0d522caecf09123db2cf0250c37a169 +Author: Nigel Croxon +Date: Thu May 14 12:20:51 2015 -0400 + + Turns out we actually need setjmp in one of gnu-efi's prominent + users, and it seems to make more sense to put it here than in + the application. + + All of these are derived from the Tiano code, but I re-wrote the + x86_64 one because we use the ELF psABI calling conventions instead + of the MS ABI calling conventions. Which is to say you probably + shouldn't setjmp()/longjmp() between functions with EFIAPI (aka + __attribute__((ms_abi))) and those without. + + Signed-off-by: Peter Jones + Signed-off-by: Nigel Croxon + +commit b5a8e93cec396381a6d2beee022abbf50100f2fd +Author: Nigel Croxon +Date: Fri Apr 10 08:49:50 2015 -0400 + + Bump version to 3.0.2 + + Signed-off-by: Nigel Croxon + +commit 01c9f11ed5ad55661e8fc8a3eee35c578564754b +Author: Nigel Croxon +Date: Fri Apr 10 08:46:40 2015 -0400 + + Fix ARM32 and AARCH64 builds + Without these added into SUBDIRS the initplat.c compilation will fail. + + Signed-off-by: Koen Kooi + Acked-by: Ard Biesheuvel + Signed-off-by: Nigel Croxon + +commit dada63fd3de148c6f8551d253355c113547cd5a0 +Author: Nigel Croxon +Date: Mon Mar 23 10:41:43 2015 -0400 + + [PATCH] _SPrint: fix NULL termination + + maxlen is the maximum string length not the buffer size. + + Signed-off-by: Jeremy Compostella + Signed-off-by: Nigel Croxon + +commit ce7098fb52e5fd4d16038964d029eb759f28eaaf +Author: Nigel Croxon +Date: Thu Feb 19 11:22:45 2015 -0500 + + Enable out-of-tree building + + This patch enables building gnu-efi outside of the source tree. + That in turn enables building for multiple architectures in parallel. + + The build directory is controlled by the OBJDIR make variable. It + defaults to the value of ARCH, and can be overridden from the command + line. + + This patch also cleans up some doubled slashes between INSTALLROOT + and PREFIX. + + Signed-off-by: Jonathan Boeing + Signed-off-by: Nigel Croxon + +commit f64cef26270bfbe04f038da33f95ae3f14c071bc +Author: Nigel Croxon +Date: Tue Jan 6 15:49:50 2015 -0500 + + Since we're keeping this in git, it'd be nice not to see a bunch + of make targets in 'status' + + Signed-off-by: Peter Jones + Signed-off-by: Nigel Croxon + +commit 322efb6b21ed0a5e42e8f124fd22bf0f8dbf01ae +Author: Nigel Croxon +Date: Mon Jan 5 13:20:43 2015 -0500 + + version number changed from VERSION = 3.0u to VERSION = 3.0.1 + + Signed-off-by: Nigel Croxon + +commit 09027207f7c18af6caa45a744fc15c90b2a829db +Author: Nigel Croxon +Date: Mon Jan 5 13:13:22 2015 -0500 + + From: Pete Batard + Date: Wed, 10 Dec 2014 21:08:34 +0000 + Subject: [PATCH] fixes for MSVC compilation + + These fixes are needed to address the following error and warnings when compiling the library part + using Visual Studio 2013 Community Edition (as in https://github.com/pbatard/uefi-simple): + * "lib\x86_64\math.c(49): error C4235: nonstandard extension used : '_asm' keyword not supported + on this architecture" + * "lib\print.c(98): error C2059: syntax error : '('" due to placement of EFIAPI macro + * "lib\cmdline.c(94): warning C4090: 'function' : different 'const' qualifiers" + * "lib\smbios.c(25): warning C4068: unknown pragma" + * Also update macro definitions in "inc\\efibind.h" for MSVC + + Signed-off-by: Pete Batard + Signed-off-by: Nigel Croxon + +commit 15805ff38b83a72c2c7c96a24bd642ee1176d819 +Author: Nigel Croxon +Date: Tue Nov 25 14:23:21 2014 -0500 + + Add README.git file. Instructions on how to archive. + + Signed-off-by: Nigel Croxon + +commit b868aa75669723b7e32f46524822e17e388fe2ba +Author: Nigel Croxon +Date: Tue Nov 25 13:26:45 2014 -0500 + + This patch makes generating releases from git a very simple process; you + simply edit the makefile's "VERSION" line to the new version, commit + that as its own commit, and do: "make test-archive". That'll make a + file in the current directory gnu-efi-$VERSION.tar.bz2 , with its top + level directory gnu-efi-$VERSION/ and the source tree under that. + + Once you've tested that and you're sure it's what you want to release, + you do "make archive", which will tag a release in git and generate a + final tarball from it. You then push to the archive, being sure to + include the tag: + + git push origin master:master --tags + + And upload the archive wherever it's supposed to go. + + Signed-off-by: Peter Jones + Signed-off-by: Nigel Croxon + +commit 530d68ba191850edafc6da22cb2df55bec0c5fa5 +Author: Nigel Croxon +Date: Tue Nov 25 10:09:50 2014 -0500 + + The gnu-efi-3.0 toplevel subdirectory is really annoying. Kill it. + + Signed-off-by: Peter Jones + Signed-off-by: Nigel Croxon + +commit 00bd66ef46b59a1623a293491a8b2c65a6d61975 +Author: Nigel Croxon +Date: Mon Nov 24 14:33:09 2014 -0500 + + FreeBSD's binutils doesn't have "-j " support, so we need to + include non-globbed versions of .rel/.rela individually. + + Signed-off-by: Peter Jones + Signed-off-by: Bill Paul + Signed-off-by: Nigel Croxon + +commit 56eb64d3c06854b9b68d61e3c2d3bdf6ff2a9853 +Author: Nigel Croxon +Date: Mon Nov 24 14:27:14 2014 -0500 + + Right now we wind up trying to build gnuefi/.o from a source file that's + an empty string. This is caused by the macros trying to generate + install rules, but there's no real reason to have all that anyway. So + just have some static install rules that are simpler and don't generate + stuff on the fly. + + Signed-off-by: Peter Jones + Signed-off-by: Nigel Croxon + +commit 65e28a90a7be9e990b360286cea31e63319217fb +Author: Nigel Croxon +Date: Mon Nov 24 12:17:45 2014 -0500 + + Add current OsIndications values. + + Signed-off-by: Peter Jones + Signed-off-by: Nigel Croxon +Date: Mon Nov 24 12:15:34 2014 -0500 + + Add the QueryVariableInfo() API. + + Signed-off-by: Peter Jones + Signed-off-by: Nigel Croxon + +commit 60efb7a2939b65a01e95aa8b535f1b756d984fba +Author: Nigel Croxon +Date: Mon Nov 24 12:13:23 2014 -0500 + + Add the capsule API. + + Signed-off-by: Peter Jones + Signed-off-by: Nigel Croxon + +commit ef08b655d1f8dfbd9a0f3a86d5685b24695ef12f +Author: Nigel Croxon +Date: Mon Nov 17 16:05:42 2014 -0500 + + Fix Table Header misspelling. Change from EFI_TABLE_HEARDER to + EFI_TABLE_HEADER. + + Signed-Off-By: Nigel Croxon + +commit 370cce41da3fff41ba38feb1262002aff2d85ffd +Author: Nigel Croxon +Date: Thu Nov 6 14:41:40 2014 -0500 + + If CROSS_COMPILE is set, ignore the ARCH value supplied on the + command line and use the target machine of the cross compiler. + + Signed-off-by: Ard Biesheuvel + Signed-off-by: Nigel Croxon + +commit d32fb845433ff6fb38e81ae0d9273454e7d18197 +Author: Nigel Croxon +Date: Thu Nov 6 14:30:03 2014 -0500 + + Allow reuse of this file beyond GPL compatible software, + update the license of crt0-efi-aarch64.S to dual 2-clause BSD/GPLv2+. + + Signed-off-by: Ard Biesheuvel + Signed-off-by: Nigel Croxon + +commit aa1df67f48f3c035fa8891e1bb311ec21500d6d9 +Author: Nigel Croxon +Date: Tue Oct 21 11:08:47 2014 -0400 + + Add the missing Variable attributes + + From: Jeremy Compostella + Date: Mon, 13 Oct 2014 17:50:50 +0200 + Subject: [PATCH] Add the missing Variable attributes + + Signed-off-by: Jeremy Compostella + Signed-off-by: Nigel Croxon + +commit 5706dff09364cbbec37f47e2fe1350747f631d74 +Author: Nigel Croxon +Date: Tue Aug 26 10:54:22 2014 -0400 + + From: David Decotigny + Date: Mon, 25 Aug 2014 13:28:49 -0700 + Subject: [PATCH] document that binutils >= 2.24 needed. + + commit ac983081 "Add support for non-PE/COFF capable objcopy" depends + on objcopy accepting wildcards for the section names. This feature is + available only with binutils >= 2.24 (binutils 2e62b7218 "PR + binutils/15033"). + + Signed-off-by: David Decotigny + Signed-off-by: Nigel Croxon + +commit 6c10e225bc759d69af520a551b9d7b37f3ae0a82 +Author: Nigel Croxon +Date: Mon Aug 25 08:51:23 2014 -0400 + + From: David Decotigny + Date: Thu, 31 Jul 2014 18:19:16 -0700 + Subject: [PATCH 5/5] allow to use external stdarg.h + + in cases we use gnu-efi together with other libs that define stdarg.h, + break the tie by telling gnu-efi to use that stdarg.h . + + Signed-off-by: David Decotigny + Signed-off-by: Nigel Croxon + +commit 16d65c0669258c8044e3549b2d9eb0cf0eb08f5a +Author: Nigel Croxon +Date: Tue Aug 19 12:07:00 2014 -0400 + + From: Ard Biesheuvel + Date: Mon, 11 Aug 2014 15:39:16 +0200 + Subject: [PATCH] Add support for 32-bit ARM + + This adds support for 32-bit ARM using an approach similar to the one used for + 64-bit ARM (AArch64), i.e., it does not rely on an objcopy that is aware of EFI + or PE/COFF, but lays out the entire PE/COFF header using the assembler. + + In the 32-bit ARM case (which does not have a division instruction), some code + has been imported from the Linux kernel to perform the division operations in + software. + + Signed-off-by: Ard Biesheuvel + Signed-off-by: Nigel Croxon + +commit b28143d4fb4f6969dc0c87c853d3527d889951d7 +Author: Nigel Croxon +Date: Fri Aug 8 15:54:19 2014 -0400 + + Updated Changelog + + Signed-off-by: Nigel Croxon + +commit 1525190354f5faac33015e17c9ba7ea2bb2be35b +Author: Nigel Croxon +Date: Fri Aug 8 15:35:09 2014 -0400 + + From: Ard Biesheuvel + Date: Fri, 8 Aug 2014 18:16:59 +0200 + Subject: [PATCH 4/4] Add support for 64-bit ARM (AArch64) + + This adds support for 64-bit ARM (AArch64) environments. Since there is no + EFI-capable objcopy for this platform, this contains a manually laid out + PE/COFF header using the assembler. + + In addition, it includes the relocation bits, some string functions that GCC + assumes are available and other glue to hold it all together. + + This can be cross built using + + make CROSS_COMPILE=aarch64-linux-gnu- + + Signed-off-by: Ard Biesheuvel + Signed-off-by: Nigel Croxon + +commit ac983081525f9483941517dfb53cf8d0163d49c0 +Author: Nigel Croxon +Date: Fri Aug 8 15:32:26 2014 -0400 + + From: Ard Biesheuvel + Date: Fri, 8 Aug 2014 17:53:42 +0200 + Subject: [PATCH 3/4] Add support for non-PE/COFF capable objcopy + + Introduce HAVE_EFI_OBJCOPY and set it if objcopy for $ARCH support PE/COOF and + EFI, i.e., it supports --target efi-[app|bsdrv|rtdrv] options. Use it to decide + whether to invoke objcopy with those options or use the linker to populate the + PE/COFF header. + + Signed-off-by: Ard Biesheuvel + Signed-off-by: Nigel Croxon + +commit fb063f0f65543b3e2bf55a39d5aa70b17a98c65e +Author: Nigel Croxon +Date: Fri Aug 8 15:26:38 2014 -0400 + + From: Ard Biesheuvel + Date: Fri, 8 Aug 2014 17:37:36 +0200 + Subject: [PATCH 2/4] Add support for cross compilation + + This changes the logic that defines ARCH (and HOSTARCH) to take CROSS_COMPILE + into account. Also, $prefix is not assigned, so that the default will be what + is on the path rather than hardcoded in /usr/bin. + + This results in the build doing the right thing if CROSS_COMPILE is set in the + environment and no ARCH or prefix options are passed to make, aligning it with + most other CROSS_COMPILE compatible projects. + + Signed-off-by: Ard Biesheuvel + Signed-off-by: Nigel Croxon + +commit 7a98d83fc32de6cf0b1ce5e12dfe80690f29fb3f +Author: Nigel Croxon +Date: Fri Aug 8 15:25:03 2014 -0400 + + From: Ard Biesheuvel + Date: Fri, 8 Aug 2014 16:50:45 +0200 + Subject: [PATCH 1/4] Restrict GNU_EFI_USE_MS_ABI GCC version test to x86_64 + + The version test only applies to x86_64 builds, so no need to do it + for other archs. + + Signed-off-by: Ard Biesheuvel + Signed-off-by: Nigel Croxon + +commit f42974dd9a7d0ea690d293f88396abd289f0014c +Author: Nigel Croxon +Date: Fri Aug 8 15:21:16 2014 -0400 + + From: David Decotigny + Date: Thu, 31 Jul 2014 13:42:23 -0700 + Subject: [PATCH 4/4] Use Shell protocols to retrieve argc/argv, when + available. + + New header files efishellintf.h efishellparm.h are coming from EDK + II, initial location and license at top of files. Only modifications: + - efishellintf.h: s/EFI_FILE_PROTOCOL/EFI_FILE/ + expand BITx macros (1< + Signed-off-by: Nigel Croxon + +commit a61fa058e9a87f966de3342b8c95fdbdcb007827 +Author: Nigel Croxon +Date: Fri Aug 8 15:17:32 2014 -0400 + + From: David Decotigny + Date: Thu, 31 Jul 2014 13:41:52 -0700 + Subject: [PATCH 3/4] document format of LoadedImage::LoadOptions data + + Signed-off-by: David Decotigny + Signed-off-by: Nigel Croxon + +commit 2f440200c855154f929d28971b2fd702ea7a207a +Author: Nigel Croxon +Date: Fri Aug 8 15:15:59 2014 -0400 + + From: David Decotigny + Date: Thu, 31 Jul 2014 13:39:37 -0700 + Subject: [PATCH 2/4] Use OpenProtocol instead of HandleProtocol + + UEFI 2.x recommends OpenProtocol instead of HandleProtocol. + + Signed-off-by: David Decotigny + Signed-off-by: Nigel Croxon + +commit 7f173da1e54f8cfe4c7c7c091ab6585af07b25ce +Author: Nigel Croxon +Date: Fri Aug 8 15:14:26 2014 -0400 + + From: David Decotigny + Date: Thu, 31 Jul 2014 13:30:07 -0700 + Subject: [PATCH 1/4] move cmdline parser to its own file + + Signed-off-by: David Decotigny + Signed-off-by: Nigel Croxon + +commit 0ad8fb87cbc59f58675b18253ad802ba51f1d132 +Author: Nigel Croxon +Date: Wed Jul 30 15:06:36 2014 -0400 + + From: David Decotigny + Date: Mon, 28 Jul 2014 21:28:50 -0700 + Subject: [PATCH 3/3] make cmdline parsing a 1st class citizen + + Refactor ParseCmdline and apps/Alloc+FreePages to factorize + boilerplate and move the new parser to the main API. + + Signed-off-by: David Decotigny + Signed-off-by: Nigel Croxon + +commit ff7ec964f2c0de0cfc4b52cfdd356003450f28bf +Author: Nigel Croxon +Date: Wed Jul 30 15:05:28 2014 -0400 + + From: David Decotigny + Date: Mon, 28 Jul 2014 21:00:52 -0700 + Subject: [PATCH 2/3] Avoid buffer overflow while parsing the cmdline args + + Signed-off-by: David Decotigny + Signed-off-by: Nigel Croxon + +commit 8d86ee202a9bb553375f56ae1d2944818112b68b +Author: Nigel Croxon +Date: Wed Jul 30 15:04:44 2014 -0400 + + From: David Decotigny + Date: Mon, 28 Jul 2014 21:01:35 -0700 + Subject: [PATCH 1/3] Fix cmdline parser + + The cmdline parser would not return the correct number of args, would + allocate one too many. Also make it clear from the declaration that we + expect a suitably lare argv. + + Signed-off-by: David Decotigny + Signed-off-by: Nigel Croxon + +commit 1ec094bfaf46a610a740dadc0150bf457dd72345 +Author: Nigel Croxon +Date: Wed Jul 23 09:54:25 2014 -0400 + + From: Julian Klode + Date: Mon, 21 Jul 2014 14:26:23 -0400 + Subject: [PATCH] inc/efistdarg.h: Use gcc builtins instead of stdarg.h or broken stubs + + We cannot use stdarg.h, as this breaks applications compiling + with -nostdinc because those will not find the header. + We also cannot use the stubs, as they just produce broken code, + as seen in the gummiboot 45-1 Debian release. + + Signed-off-by: Julian Klode + Signed-off-by: Nigel Croxon + +commit 6caab22f23434f41f42cfe7591d9a7ae66de9f0a +Author: Nigel Croxon +Date: Thu Jun 19 10:39:23 2014 -0400 + + From: Laszlo Ersek + Date: Mon, 2 Jun 2014 23:26:48 +0200 + Subject: [PATCH] always observe EFIAPI calling convention when calling + STO.SetAttribute + + We have to consider the following cases wrt. the PRINT_STATE.Output and + PRINT_STATE.SetAttr EFIAPI function pointers, especially when building for + x86_64 with gcc: + + (1) The compiler is new enough, and EFIAPI actually ensures the Microsoft + calling convention. In this case everything happens to work fine even + if we forget uefi_call_wrapper(), because the wrapper would expand to + a normal C function call anyway. + + (2) Otherwise (ie. gcc is old), EFIAPI expands to nothing, and we must + take into account the called function's origin: + + (2a) If the callee that is declared EFIAPI is *defined* inside gnu-efi, + then EFIAPI means nothing for the callee too, so caller and callee + only understand each other if the caller intentionally omits + uefi_call_wrapper(). + + (2b) If the callee that is declared EFIAPI is defined by the platform + UEFI implementation, then the caller *must* use + uefi_call_wrapper(). + + The PRINT_STATE.Output EFIAPI function pointer is dereferenced correctly: + the PFLUSH() distinguishes cases (2a) from (2b) by using IsLocalPrint(). + + However use of the PRINT_STATE.SetAttr EFIAPI function pointer is not + always correct: + + - The PSETATTR() helper function always relies on the wrapper (case (2b)). + This is correct, because PRINT_STATE.SetAttr always points to a + platform-provided function. + + - The DbgPrint() function contains two incorrect calls: they mistakenly + assume case (2a) (or case (1)), even though the pointer always points to + a platform function, implying (2b). (The error is masked in case (1).) + Fix them. + + Signed-off-by: Laszlo Ersek + Signed-off-by: Nigel Croxon + +commit ecfd1ded9a799c3a572d4eb7fbb52582fe4d3390 +Author: Nigel Croxon +Date: Tue Jun 10 12:59:09 2014 -0400 + + Add VPoolPrint Function + + Equivalent to PoolPrint but using a va_list parameter + + Signed-off-by: Sylvain Chouleur + Signed-off-by: Nigel Croxon + +commit f16d93f3b9e314336a387a3885c7fd2f176c41d3 +Author: Nigel Croxon +Date: Fri May 16 11:33:51 2014 -0400 + + Revert "The prototype of DbgPrint() is incorrect, at the end of "inc/efidebug.h"." + A problem was found compiling on GCC 4.8. + + This reverts commit 644898eabc06c8efaa3aa54f84cdd468960a2f6c. + +commit 644898eabc06c8efaa3aa54f84cdd468960a2f6c +Author: Nigel Croxon +Date: Wed May 14 09:09:47 2014 -0400 + + The prototype of DbgPrint() is incorrect, at the end of "inc/efidebug.h". + Consequently, when your program calls DbgPrint() via the DEBUG() macro, + it fails to set up the stack correctly (it does not pass the arguments + through the ellipsis (...) according to the EFIAPI calling convention). + However, va_start() inside DbgPrint() *assumes* that stack. + + Signed-off-by: Laszlo Ersek + Signed-off-by: Nigel Croxon + +commit 8921ba2fc5f6163bdad3b5902c5d9d638415dde0 +Author: Nigel Croxon +Date: Mon Apr 14 18:49:23 2014 -0400 + + Cleaned up compile warnings. + + Signed-off-by: Nigel Croxon + +commit 42cca551dbf1c0be9e02e8d3d3c417ce35749638 +Author: Nigel Croxon +Date: Mon Apr 14 14:04:11 2014 -0400 + + Module lib/ParseCmdLine.c has errors, it incorrectly mixes "char" and "CHAR16" + and uses a pointer to argv[] like it's argv[]. The compiler only issues + warnings though. Here is a patch to remove compiler warnings and make the + code behave. + + Signed-off-by: Bernard Burette + Signed-off-by: Nigel Croxon + +commit 4e8460f1aedd2724de876be5b154eb5752bfada5 +Author: Nigel Croxon +Date: Mon Apr 14 13:53:03 2014 -0400 + + Here is a very small patch to remove a compiler warning when processing lib/smbios.c. + + Signed-off-by: Bernard Burette + Signed-off-by: Nigel Croxon + +commit 6a0875ca2fcb67e7d1a1e2d15f3bcc645329dc75 +Author: Nigel Croxon +Date: Mon Apr 14 13:45:16 2014 -0400 + + Here is a very small patch to remove compiler warning in function + "LibLocateHandleByDiskSignature()" because the "Start" variable is + give a value which is not used. + + Signed-off-by: Bernard Burette + Signed-off-by: Nigel Croxon + +commit d5f35dfb8008ba65bcc641559accd9bc13386ef9 +Author: Nigel Croxon +Date: Mon Apr 14 13:40:29 2014 -0400 + + Here is a very small patch to remove *~ files in include diretory. + + Signed-off-by: Bernard Burette + Signed-off-by: Nigel Croxon + +commit 1a04669a7bb022984c9b54a0f73d7d67a2540fb7 +Author: Nigel Croxon +Date: Mon Apr 14 12:45:57 2014 -0400 + + Here is a patch for "DevicePathToStr()" to display device path according to UEFI 2 specification. + The path is in the two files inc/efidevp.h and lib/dpath.c. + + It also add the Sata device path and removes the "/?" path for unknown device paths. + + Signed-off-by: Bernard Burette + Signed-off-by: Nigel Croxon + +commit 3c62e78556aea01e9798380cd46794c6ca09d4bd +Author: Nigel Croxon +Date: Tue Apr 1 10:26:44 2014 -0400 + + Removed GPL code setjmp_ia32.S, setjmp_ia64.S, setjmp_x86_64.S + Not used anymore. + + Signed-off-by: Nigel Croxon + +commit f9baa4f622cf34576d73e00d4a774a31f0f81fd7 +Author: Nigel Croxon +Date: Mon Mar 31 08:37:56 2014 -0400 + + Remove incumbent GPL 'debian' subdiretory. + Update ChangeLog + + Signed-off-by: Nigel Croxon + + +Changelog format change from here and above to 'git log' style. + +2014-04-01 Nigel Croxon + + Removed GPL code setjmp_ia32.S, setjmp_ia64.S, setjmp_x86_64.S + Not used anymore. + + Signed-off-by: Nigel Croxon + +2014-03-17 Nigel Croxon + + Add support for the simple pointer and absolute pointer protocols + + Signed-off-by: John Cronin + Signed-off-by: Nigel Croxon + +2014-03-14 Nigel Croxon + + Trying to recurse into subdirectories of object files may lead + to an error if the directory doesn't exist. Even when cleaning. + + Signed-off-by: Sylvain Gault + Signed-off-by: Nigel Croxon + +2014-03-14 Nigel Croxon + + Make install used to copy files unconditionnally to their + destination. However, if the destination is used by another + Makefile, it will always see modified files. "install" target + now only updates the files when they need to. + + Signed-off-by: Sylvain Gault + Signed-off-by: Nigel Croxon + +2014-02-13 Nigel Croxon + + Patch GNU-EFI to remove the ELILO code + + Signed-off-by: Jerry Hoemann + Signed-off-by: Nigel Croxon + +2014-02-13 Nigel Croxon + + Initialize Status before calling GrowBuffer() + Status must be initialized before calling GrowBuffer() as it may + otherwise be uninitialized or set to EFI_BUFFER_TOO_SMALL by + other functions. + + Signed-off-by: Gene Cumm + Signed-off-by: Nigel Croxon + +2014-01-23 Nigel Croxon + + These changes allow manually overridden SRCDIR (current source + directory) and TOPDIR (top of source tree) to separate the + build directory from the source tree. + + Signed-off-by: Gene Cumm + Signed-off-by: Nigel Croxon + +2014-01-16 Nigel Croxon + compilation: fix uninitialized variables warning + + Signed-off-by: Jeremy Compostella + Signed-off-by: Nigel Croxon + +2014-01-13 Nigel Croxon + Implement VSPrint function, prints a formatted unicode string to a buffer. + + Signed-off-by: Jeremy Compostella + Signed-off-by: Nigel Croxon + +2014-01-10 Nigel Croxon + Created lib/argify.c and inc/argify.h containing the function argify. + It contains verbatim copy of the comment at beginning of file from + elilo. + There was no COPYING file in the elilo source that the comment refers to. + + Signed-off-by: Jerry Hoemann + Signed-off-by: Nigel Croxon + +2014-01-08 Nigel Croxon + The information needed is not really the host architecture as given by + the kernel arch. The information actually needed is the default target + of gcc. + + Signed-off-by: Sylvain Gault + Signed-off-by: Nigel Croxon + +2013-10-11 Nigel Croxon + Added support for SetVariable to store volatile variable, + and SetNVVariable to store non volatile variable. + + Signed-off-by: Sylvain Chouleur + Signed-off-by: Nigel Croxon + +2013-10-07 Nigel Croxon + + Atoi needs to have consistent declaration/definition. + + Signed-off-by: Nigel Croxon + +2013-10-07 Nigel Croxon + if you have a function that takes const arguments and then + e.g. tries to copy StrCmp, gcc will give you warnings about those + calls, and the warnings are right. These clutter up other things + you might miss that you should be more concered about. + + You could work around it through vigorous typecasting + to non-const types, but why should you have to? All of these + functions are regorously defined as not changing their input + - it is const, and should be marked as such. + + Signed-off-by: Peter Jones + +2013-10-02 Nigel Croxon + + Added two simple applications to allocate/free memory at EFI. + Used to test/find memory fragmentation issues linux. + + Signed-off-by: Jerry Hoemann + Signed-off-by: Nigel Croxon + +2013-06-25 Nigel Croxon + Sample boot service driver. + + Signed-off-by: David Decotigny + +2013-06-25 Nigel Croxon +Date: Tue Jun 25 08:47:03 2013 -0400 + + Be more pedantic when linking, don't allow duplicate symbols, + abort upon first error. Also make sure linker script comes + last for apps. + + Signed-off-by: David Decotigny + +2013-06-25 Nigel Croxon + Fix compilation on x86_64 without HAVE_USE_MS_ABI + make -C apps would fail on tcc.c because uefi_call_wrapper() + doesn't deal correctly with efi_callO-type invocation. + + Signed-off-by: David Decotigny + +2013-06-12 Nigel Croxon + Fix typo when disabling mno-mmx + + Signed-Off-By: Nigel Croxon + +2013-06-12 Nigel Croxon + Disable MMX and SSE + + GCC 4.8.0 adds some optimizations that will use movups/movaps (and use + %xmm* registers) when they're faster, and of course that won't work at + all since UEFI firmwares aren't guaranteed to initialize the mmx/sse + instructions. + + This will be even more annoying, since most UEFI firmwares don't + initialize the #DE or #UD trap handlers, and your backtrace will be a + random path through uninitialized memory, occasionally including + whatever address the IDT has for #UD, but also addresses like "0x4" and + "0x507" that you don't normally expect to see in your call path. + + Signed-off-by: Peter Jones + + Author: Nigel Croxon + Date: Wed Jun 12 10:29:40 2013 -0400 + + bug in make 3.82 expand to odd values + + Some Makefiles tickle a bug in make 3.82 that cause libefi.a + and libgnuefi.a dependencies to expand to the odd values: + + libefi.a: boxdraw.o) smbios.o) ... + libgnuefi.a(reloc_x86_64.o: + + The patch replaces libgnuefi.a($(OBJS)) & libefi.a($(OBJS)) + with an equivalent expansion that should work with any make + that supports $(patsubst). + + Author: Nigel Croxon + Date: Wed Jun 12 09:53:01 2013 -0400 + + support .text.* sections on x86_64 + + Group them in .text. Also add vague linkage sections in .text. + + Signed-off-by: David Decotigny + + Author: Nigel Croxon + Date: Wed Jun 12 09:51:36 2013 -0400 + + cleanup and fix Make.defaults + + Reorder variables in Make.defaults so that they are grouped by + functions. Also fixed ifeq (x,y) to have required syntax and make it + work for ARCH amd64->x86_64 renaming on BSD. Also provides top-level + Makefile with a "mkvars" target that displays effective variables. + + Signed-off-by: David Decotigny + + Author: Nigel Croxon + Date: Wed Jun 12 09:47:16 2013 -0400 + + automatically determine number of uefi_call_wrapper() args on x86_64 + + Instead of asking developers to explicitly pass the number of + parameters to the functions that get called, we determine them + automatically at preprocessing time. This should result in more + robust code. + + Argument va_num is now ignored in x86_64 code, both with and + without HAVE_USE_MS_ABI. + + Credits to the macro magic given in the comments. + + Signed-off-by: David Decotigny + + Author: Nigel Croxon + Date: Wed Jun 12 09:38:10 2013 -0400 + + fix parameter-passing corruption on x86_64 for >= 5 args + + On x86_64 without HAVE_USE_MS_ABI support, uefi_call_wrapper() is a + variadic function. Parameters >=5 are copied to the stack and, when + passed small immediate values (and possibly other parameters), gcc + would emit a movl instruction before calling uefi_call_wrapper(). As a + result, only the lower 32b of these stack values are significant, the + upper 32b potentially contain garbage. Considering that + uefi_call_wrapper() assumes these arguments are clean 64b values + before calling the efi_callX() trampolines, the latter may be passed + garbage. This makes calling functions like + EFI_PCI_IO_PROTOCOL.Mem.Read()/Write() or BS->OpenProtocol() quite + unreliable. + + This patch fixes this by turning uefi_call_wrapper() into a macro that + allows to expose the efi_callX() trampoline signatures to the callers, + so that gcc can know upfront that it has to pass all arguments to + efi_callX() as clean 64b values (eg. movq for immediates). The + _cast64_efi_callX macros are just here to avoid a gcc warning, they do + nothing otherwise. + + Signed-off-by: David Decotigny + + Author: noxorc + Date: Wed May 15 15:26:16 2013 -0400 + + - Removes the ElfW() macro usage from reloc_ia32.c and reloc_x86_64.c. These + macros only exist in link.h on Linux. On FreeBSD, the equivalent macro is + __ElfN(). But the macro usage is redundant. You're only going to compile the + ia32 file for IA32 binaries and the x86_64 file for X64 binaries. If you had + just one file built for both cases, then using the macro might make more + sense. + + - Removes the "#define foo_t efi_foo_t" macros from reloc_ia32.c and + reloc_x86_64.c. + + - Modifies inc/x86_64/efibind.h and inc/ia32/efibind.h to use the new + definitions for uint64_t, int64_t and int8_t. The 64-bit types are now defined + as: + + typedef int __attribute__((__mode__(__DI__))) int64_t; + typedef unsigned int __attribute__((__mode__(__DI__))) uint64_t; + + This removes the conflict between the host types dragged in by elf.h and the + type definitions in efibind.h that made the #define foo_t efi_foo_t" hack + necessary. Also, int8_t is now defined as signed char instead of just char + (assuming char == signed char is apparently not good enough). + + - Also modifies these files to use stdint.h instead of stdint-gcc.h. It's + unclear if this is completely correct, but stdint-gcc.h is not present with + all GCC installs, and if you use -std=c99 or later you will force this case to + be hit. This also can break clang, which doesn't have a stdint-gcc.h at all. + + - Removes the #include of from reloc_ia32.c and reloc_x86_64.c (since + with the previous changes it's not needed anymore). + + - Places the #include of after #include /#include so + that we know the types will always be defined properly, in case you build on a + system where doesn't automatically pull in the right header files to + define all the needed types. (This actually happens on VxWorks. It's harmless + elsewhere. If you don't care about VxWorks, you can leave this out.) + + - Modifies setjmp_ia32.S and setjmp_x86_64.S so to change "function" to + @function. The clang compiler doesn't like the former. Clang and GCC both like + the latter. + + - Modifles Make.defaults so that if ARCH is detected as "amd64," it's changed + to "x86_64." It happens that uname -m on 64-bit FreeBSD reports the former + rather than the latter, which breaks the build. This may also be the case on + some other OSes. There's a way to force uname(1) to return x86_64 as the + machine type, but this way is a little friendlier. + + - Creates gnuefi/elf_ia32_fbsd_efi.lds which specifies the object file type as + elf-ia32-freebsd. This is required for building on FreeBSD/i386, not just + FreeBSD/amd64. + + - Modifies apps/Makefile to always use + $(TOPDIR)/gnuefi/elf_$(ARCH)_fbsd_efi.lds when building on either 32-bit or + 64-bit FreeBSD instead of just for the x86_64 case. + + - Changed LDFLAGS in Make.defaults to include --no-undefined. This will cause + linking to fail if there are any unsatisfied symbols when creating foo.so + during any of the app builds, as opposed to just silently succeeding and + producing an unusable binary. + + - Changed CFLAGS to include -ffreestanding -fno-stack-protector -fno-stack- + check. This prevents clang from inserting a call to memset() when compiling + the RtZeroMem() and RtSetMem() routines in lib/runtime/efirtlib.c and guards + against the native compiler in some Linux distros from adding in stack + checking code which relies on libc help that isn't present in the EFI runtime + environment. + + This does the following: + + - Cleans up the ia32 and x86-64 relocation code a bit (tries to break the + dependency between the host ELF headers and the EFI runtime environment) + - Avoids the dependency on stdint-gcc.h which may not always be available + - Allows GNU EFI to build out of the box on both FreeBSD/i386 and + FreeBSD/amd64 + - Allows GNU EFI to build out of the box with either GCC or clang on + FreeBSD/i386 and FreeBSD/amd64 9.0 and later. + - Makes things a little easier to port to VxWorks + - Avoids creating un-runable binaries with unresolved symbol definitions + (which can be very confusing to debug) + + Author: noxorc + Date: Wed May 8 16:29:45 2013 -0400 + + Add the definitions for TCP, UDP and IP, for both IPv4 and IPv6. + + +2013-05-02 Nigel Croxon + * Chnage from Matt Fleming + - Preparation for adding the networking protocol definitions. + Add the service binding protocol. + +2013-02-21 Nigel Croxon + * Change from Peter Jones + - Previously we were incorrectly passing 3 functions with + the System V ABI to UEFI functions as EFI ABI functions. + Mark them as EFIAPI so the compiler will (in our new + GNU_EFI_USE_MS_ABI world) use the correct ABI. + - These need to be EFIAPI functions because in some cases + they call ST->ConOut->OutputString(), which is an EFIAPI + function. (Which means that previously in cases that + needed "cdecl", these didn't work right.) + - If the compiler version is new enough, and GNU_EFI_USE_MS_ABI + is defined, use the function attribute ms_abi on everything + defined with "EFIAPI". Such calls will no longer go through + efi_call*, and as such will be properly type-checked. + - Honor PREFIX and LIBDIR correctly when passed in during the build. + - Add machine type defines for i386, arm/thumb, ia64, ebc, x86_64. + - __STDC_VERSION__ never actually gets defined unless there's a + --std=... line. So we were accidentally defining lots of c99 + types ourself. Since it's 2012, use --std=c11 where appropriate, + and if it's defined and we're using gcc, actually include gcc's + stdint definitions. + - New test application added: route80h. This is a test program + for PciIo. It routes ioport 80h on ICH10 to PCI. This is also + useful on a very limited set of hardware to enable use of + a port 80h debug card. + - New test applcation added: modelist. This lists video modes + the GOP driver is showing us. + * Change from Finnbarr Murphy + - https://sourceforge.net/p/gnu-efi/feature-requests/2/ + Please add the following status codes to + EFI_INCOMPATIBLE_VERSION 25 + EFI_SECURITY_VIOLATION 26 + EFI_CRC_ERROR 27 + EFI_END_OF_MEDIA 28 + EFI_END_OF_FILE 31 + EFI_INVALID_LANGUAGE 32 + EFI_COMPROMISED_DATA 33 + * Change from SourceForge.net Bug report + - https://sourceforge.net/p/gnu-efi/bugs/5/ + BufferSize is a UINT64 *. The file shipped with GNU EFI is from + 1998 whereas the latest one is from 2004. I suspect Intel changed + the API in order handle 64-bit systems. + * Change from Felipe Contreras + - The current code seems to screw the stack at certain points. + Multiple people have complained that gummiboot hangs right away, + which is in part the fault of gummiboot, but happens only + because the stack gets screwed. x86_64 EFI already aligns the + stack, so there's no need for so much code to find a proper + alignment, we always need to shift by 8 anyway. + * Change from A. Steinmetz + - https://sourceforge.net/p/gnu-efi/patches/1/ + The patch prepares for elilo to support uefi pxe over ipv6 + See uefi spec 2.3.1 errata c page 963 as reference. + Verfied on an ASUS Sabertooth X79 BIOS Rev. 2104 system which + is able to do an IPv6 UEFI PXE boot. + * Release 3.0t + +2012-09-21 Nigel Croxon + * Change from Peter Jones + - EFI Block I/O protocol versions 2 and 3 provide more information + regarding physical disk layout, including alingment offset at the + beginning of the disk ("LowestAlignedLba"), logical block size + ("LogicalBlocksPerPhysicalBlock"), and optimal block transfer size + ("OptimalTransferLengthGranularity"). + * Release 3.0r + +2012-04-30 Nigel Croxon + * Change from Matt Fleming + - The .reloc section is now 4096-byte boundary for x86_64. + Without this patch the .reloc section will not adhere to + the alignment value in the FileAlignment field (512 bytes by + default) of the PE/COFF header. This results in a signed + executable failing to boot in a secure boot environment. + * Release 3.0q + +2011-12-12 Nigel Croxon + * Changes from Fenghua Yu + - This fixes redefined types compilation failure for tcc.c on x86_64 machines. + * Release 3.0p + +2011-11-15 Nigel Croxon + * Changes from Darren Hart + - Conditionally assign toolchain binaries to allow overriding them. + - Force a dependency on lib for gnuefi. + * Release 3.0n + +2011-08-23 Nigel Croxon + * Changes from Peter Jones + - Add guarantee 16-byte stack alignment on x86_64. + - Add routine to make callbacks work. + - Add apps/tcc.efi to test calling convention. + * Release 3.0m + +2011-07-22 Nigel Croxon + * Changed Makefiles from GPL to BSD. + * Changes from Peter Jones + - Add ifdefs for ia64 to mirror ia32 and x86-64 so that + one can build with GCC. + - Add headers for PciIo. + - Add the UEFI 2.x bits for EFI_BOOT_SERVICES + - Add an ignore for .note.GNU-stack section in X86-64 linker maps. + * Release 3.0l + +2011-04-07 Nigel Croxon + * Change license from GPL to BSD. + * Release 3.0j + +2009-09-12 Julien BLACHE + * Add support for FreeBSD. + * Release 3.0i + +2009-09-11 Julien BLACHE + * Fix elf_ia32_efi.lds linker script to be compatible with the new + linker behaviour. Patch from the RedHat bugzilla 492183. + +2009-06-18 Nigel Croxon + * Release 3.0h + +2008-11-06 Nigel Croxon + * Fix to not having any relocations at all. + +2008-09-18 Nigel Croxon + * Use LIBDIR in makefiles + * Add setjmp/longjmp + * Fixes incorrect section attribute in crt0-efi-ia32.S + * Adds value EfiResetShutdown to enum EFI_RESET_TYPE + * Fixes a RAW warning in reloc_ia64.S + * Adds the USB HCI device path structure in the headers + patches were supplied by Peter Jones @ RedHat + +2008-02-22 Nigel Croxon + * Added '-mno-red-zone' to x68_64 compiles. + Patch provided by Mats Andersson. + +2008-01-23 Nigel Croxon + * release 3.0e to support x86_64 + EFI calling convention, the stack should be aligned in 16 bytes + to make it possible to use SSE2 in EFI boot services. + This patch fixes this issue. Patch provided by Huang Ying from Intel. + +2007-05-11 Nigel Croxon + * release 3.0d to support x86_64 from Chandramouli Narayanan + from Intel and based on 3.0c-1 + +2006-03-21 Stephane Eranian + * merged patch to support gcc-4.1 submitted by + Raymund Will from Novell/SuSE + +2006-03-20 Stephane Eranian + * updated ia-64 and ia-32 linker scripts to + match latest gcc. The new gcc may put functions in + .text* sections. patch submitted by H.J. Lu from Intel. + +2004-11-19 Stephane Eranian + * added patch to ignore .eh_frame section for IA-32. Patch + submitted by Jim Wilson + +2004-09-23 Stephane Eranian + * added patch to discard unwind sections, newer toolchains + complained about them. Patch submitted by Jesse Barnes from SGI. + +2003-09-29 Stephane Eranian + * updated elf_ia64_efi.lds to reflect new data sections + created by gcc-3.3. Patch provided by Andreas Schwab from Suse. + +2003-06-20 Stephane Eranian + * updated elf_ia64_efi.lds and elf_ia32_efi.lds to include + new types data sections produced by recent version of gcc-3.x + +2002-02-22 Stephane Eranian + * release 3.0a + * modified both IA-64 and IA-32 loader scripts to add support for the + new .rodata sections names (such as rodata.str2.8). Required + for new versions of gcc3.x. + +2001-06-20 Stephane Eranian + * release 3.0 + * split gnu-efi package in two different packages: the libary+include+crt and the bootloader. + * removed W2U() hack and related files to get from wide-char to unicode. + * Use -fshort-wchar option for unicode. + * restructured Makefiles now install under INSTALLROOT. + +2001-04-06 Stephane Eranian + + * incorporated patches from David and Michael Johnston at Intel + to get the package to compile for IA-32 linux target. + + * Fixed ELILO to compile for Ia-32 (does not execute yet, though): + Makefile and start_kernel() function. + +2001-04-06 Andreas Schwab + + * Fixed config.c to + get the timeout directive to do something. implemented the global + root= directive. + + * Fix the efi_main() to deal with the -C option properly + +2001-04-05 Stephane Eranian + + * update efi library to latest EFI toolkit 1.02 as distributed + by Intel. Fixed header + library files to compile with GCC + + * merged ELI and LILO (as of gnu-efi-1.1) together, mostly + taking the config file feature of ELI. + + * renamed LILO to ELILO to make the distinction + + * restructured code to make it easier to understand and maintain + + * fixed FPSWA driver checking and loading: we try all possible + files and let the driver itself figure out if it is the most + recent. + * added support for compression (gzip) but keep support for plain + ELF image. ELILO autodetects the format + + * change the way the kernel is invoked. Now we call it in + physical memory mode. This breaks the dependency between the + kernel code and the loader. No more lilo_start.c madness. + + * changed the way the boot_params are passed. We don't use the + ZERO_PAGE_ADDR trick anymore. Instead we use EFI runtime memory. + The address of the structure is passed to the kernel in r28 + by our convention. + + * released as gnu-efi-2.0 + +2001-04-03 David Mosberger + + * gnuefi/reloc_ia32.c (_relocate): Change return type from "void" + to "int". Return error status if relocation fails for some + reason. + + * gnuefi/elf_ia32_efi.lds: Drop unneeded ".rel.reloc" section. + + * gnuefi/crt0-efi-ia32.S (_start): Exit if _relocate() returns with + non-zero exit status. + + * inc/ia32/efibind.h [__GNUC__]: Force 8-byte alignment for 64-bit + types as that is what EFI appears to be expecting, despite the + "#pragma pack()" at the beginning of the file! + +2001-03-29 David Mosberger + + * gnuefi/reloc_ia32.c: Add a couple of defines to work around + libc/efilib collision on uint64_t et al. + (_relocate): Use ELF32_R_TYPE() instead of ELFW(R_TYPE)(). + + * gnuefi/crt0-efi-ia32.S (dummy): Add a dummy relocation entry. + +2001-03-29 David Mosberger + + * gnuefi/reloc_ia32.c: Add a couple of defines to work around + libc/efilib collision on uint64_t et al. + (_relocate): Use ELF32_R_TYPE() instead of ELFW(R_TYPE)(). + + * gnuefi/crt0-efi-ia32.S (dummy): Add a dummy relocation entry. + +2000-10-26 David Mosberger + + * gnuefi/elf_ia64_efi.lds: Mention .rela.sdata. + + * Make.defaults (CFLAGS): Remove -nostdinc flags so we can pick + up the C compiler's stdarg.h. + + * inc/stdarg.h: Remove this file. It's not correct for gcc (nor + most other optimizing compilers). + +2000-10-10 Stephane Eranian + + * cleaned up the error message and printing of those. + * added support to load the FPSWA from a file in case support is not + present in the firmware already + * fixed split_args() to do the right thing when you have leading spaces + before kernel name + * changed the argify() function to rely on \0 instead of LoadOptionSize + as the field seems to be broken with current firmware + * bumped version to 1.0 + +2000-10-04 David Mosberger + + * gnuefi/reloc_ia64.S: Reserve space for up to 750 function descriptors. + + * gnuefi/elf_ia64_efi.lds: Add .sdata section for small data and + put __gp in the "middle" of it. + + * gnuefi/crt0-efi-ia64.S (_start): Use movl/add to load + gp-relative addresses that could be out of the range of the addl + offset. + * gnuefi/reloc_ia64.S (_relocate): Ditto. + + * apps/Makefile: Remove standard rules and include Make.rules instead. + * lilo/Makefile: Ditto. + + * Make.rules: New file. + +2000-08-04 Stephane Eranian + * released version 0.9 + * incorporated ACPI changes for Asuza by NEC < kouchi@hpc.bs1.fc.nec.co.jp> + * added support for initrd (-i option) original ELI code from Bill Nottingham ) + * lots of cleanups + * got rid of #ifdef LILO_DEBUG and uses macro instead + * fix a few extra memory leaks in create_boot_params() + * added exit capability just before starting the kernel + +2000-06-22 David Mosberger + + * gnuefi/elf_ia64_efi.lds: Add .srodata, .ctors, .IA64.unwind, + .IA64.unwind_info to .data section and .rela.ctors to .rela + section. + +2000-04-03 David Mosberger + + * lilo/lilo.c (LILO_VERSION): Up version number to 0.9. + + * gnuefi/elf_ia64_efi.lds: Include .IA_64.unwind and + .IA_64.unwind_info in .data segment to avoid EFI load error + "ImageAddress: pointer outside of image" error due to the .dynsym + relocations against these sections. + + * ChangeLog: Moved from lilo/ChangeLogs. + + * gnuefi/reloc_ia64.S: fixed typo: .space directive had constant + 100 hardcoded instead of using MAX_FUNCTION_DESCRIPTORS + macro. Duh. + +2000-03-17 Stephane Eranian + + * Released 0.8 + * replace the getopt.c with new version free with better license + * created a documentation file + * fix a couple of memory leaks + * code cleanups + * created a separate directory for lilo in the gnu-efi package. + * added support for the BOOT_IMAGE argument to kernel + * default is to build natively now + diff --git a/gnu-efi/Make.defaults b/gnu-efi/Make.defaults new file mode 100644 index 0000000..5695b2a --- /dev/null +++ b/gnu-efi/Make.defaults @@ -0,0 +1,183 @@ +# -*- makefile -*- +# Copyright (c) 1999-2007 Hewlett-Packard Development Company, L.P. +# Contributed by David Mosberger +# Contributed by Stephane Eranian +# +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following +# disclaimer in the documentation and/or other materials +# provided with the distribution. +# * Neither the name of Hewlett-Packard Co. nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND +# CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +# INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS +# BE LIABLE FOR ANYDIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, +# OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR +# TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF +# THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. +# + +TOPDIR := $(shell if [ "$$PWD" != "" ]; then echo $$PWD; else pwd; fi) + +# +# Variables below overridable from command-line: +# make VARNAME=value ... +# + +# +# Where to install the package. GNU-EFI will create and access +# lib and include under the root +# +INSTALLROOT := / +PREFIX := /usr/local +LIBDIR := $(PREFIX)/lib +INSTALL := install + +# Compilation tools +HOSTCC := $(prefix)gcc +CC := $(prefix)$(CROSS_COMPILE)gcc +AS := $(prefix)$(CROSS_COMPILE)as +LD := $(prefix)$(CROSS_COMPILE)ld +AR := $(prefix)$(CROSS_COMPILE)ar +RANLIB := $(prefix)$(CROSS_COMPILE)ranlib +OBJCOPY := $(prefix)$(CROSS_COMPILE)objcopy + + +# Host/target identification +OS := $(shell uname -s) +HOSTARCH ?= $(shell $(HOSTCC) -dumpmachine | cut -f1 -d- | sed -e s,i[3456789]86,ia32, -e 's,armv[67].*,arm,' ) +ARCH ?= $(shell $(HOSTCC) -dumpmachine | cut -f1 -d- | sed -e s,i[3456789]86,ia32, -e 's,armv[67].*,arm,' ) + +# Get ARCH from the compiler if cross compiling +ifneq ($(CROSS_COMPILE),) + override ARCH := $(shell $(CC) -dumpmachine | cut -f1 -d-| sed -e s,i[3456789]86,ia32, -e 's,armv[67].*,arm,' ) +endif + +# FreeBSD (and possibly others) reports amd64 instead of x86_64 +ifeq ($(ARCH),amd64) + override ARCH := x86_64 +endif + +# +# Where to build the package +# +OBJDIR := $(TOPDIR)/$(ARCH) + +# +# Variables below derived from variables above +# + +# Arch-specific compilation flags +CPPFLAGS += -DCONFIG_$(ARCH) + +CFLAGS += -Wno-error=pragmas + +ifeq ($(ARCH),ia64) + CFLAGS += -mfixed-range=f32-f127 +endif + +ifeq ($(ARCH),ia32) + CFLAGS += -mno-mmx -mno-sse + ifeq ($(HOSTARCH),x86_64) + ARCH3264 = -m32 + endif +endif + +ifeq ($(ARCH),x86_64) + GCCVERSION := $(shell $(CC) -dumpversion | cut -f1 -d.) + GCCMINOR := $(shell $(CC) -dumpversion | cut -f2 -d.) + USING_CLANG := $(shell $(CC) -v 2>&1 | grep -q 'clang version' && echo clang) + + # Rely on GCC MS ABI support? + GCCNEWENOUGH := $(shell ( [ $(GCCVERSION) -gt "4" ] \ + || ( [ $(GCCVERSION) -eq "4" ] \ + && [ $(GCCMINOR) -ge "7" ] ) ) \ + && echo 1) + ifeq ($(GCCNEWENOUGH),1) + CPPFLAGS += -DGNU_EFI_USE_MS_ABI -maccumulate-outgoing-args --std=c11 + else ifeq ($(USING_CLANG),clang) + CPPFLAGS += -DGNU_EFI_USE_MS_ABI --std=c11 + endif + + CFLAGS += -mno-red-zone + ifeq ($(HOSTARCH),ia32) + ARCH3264 = -m64 + endif +endif + +ifneq (,$(filter $(ARCH),ia32 x86_64)) + # Disable AVX, if the compiler supports that. + CC_CAN_DISABLE_AVX=$(shell $(CC) -Werror -c -o /dev/null -xc -mno-avx - /dev/null 2>&1 && echo 1) + ifeq ($(CC_CAN_DISABLE_AVX), 1) + CFLAGS += -mno-avx + endif +endif + +ifeq ($(ARCH),mips64el) + CFLAGS += -march=mips64r2 + ARCH3264 = -mabi=64 +endif + +# +# Set HAVE_EFI_OBJCOPY if objcopy understands --target efi-[app|bsdrv|rtdrv], +# otherwise we need to compose the PE/COFF header using the assembler +# +ifneq ($(ARCH),aarch64) +ifneq ($(ARCH),arm) +ifneq ($(ARCH),mips64el) +export HAVE_EFI_OBJCOPY=y +endif +endif +endif + +ifneq ($(ARCH),arm) +export LIBGCC=$(shell $(CC) $(ARCH3264) -print-libgcc-file-name) +endif + +ifeq ($(ARCH),arm) +CFLAGS += -marm +endif + +# Generic compilation flags +INCDIR += -I$(SRCDIR) -I$(TOPDIR)/inc -I$(TOPDIR)/inc/$(ARCH) \ + -I$(TOPDIR)/inc/protocol + +# Only enable -fpic for non MinGW compilers (unneeded on MinGW) +GCCMACHINE := $(shell $(CC) -dumpmachine) +ifneq (mingw32,$(findstring mingw32, $(GCCMACHINE))) + CFLAGS += -fpic +endif + +ifeq (FreeBSD, $(findstring FreeBSD, $(OS))) +CFLAGS += $(ARCH3264) -g -O2 -Wall -Wextra -Werror \ + -fshort-wchar -fno-strict-aliasing \ + -ffreestanding -fno-stack-protector +else +CFLAGS += $(ARCH3264) -g -O2 -Wall -Wextra -Werror \ + -fshort-wchar -fno-strict-aliasing \ + -ffreestanding -fno-stack-protector -fno-stack-check \ + -fno-stack-check \ + $(if $(findstring gcc,$(CC)),-fno-merge-all-constants,) +endif + +ARFLAGS := rDv +ASFLAGS += $(ARCH3264) +LDFLAGS += -nostdlib --warn-common --no-undefined --fatal-warnings \ + --build-id=sha1 diff --git a/gnu-efi/Make.rules b/gnu-efi/Make.rules new file mode 100644 index 0000000..8cb93b0 --- /dev/null +++ b/gnu-efi/Make.rules @@ -0,0 +1,64 @@ +# +# Copyright (C) 1999-2007 Hewlett-Packard Co. +# Contributed by David Mosberger +# Contributed by Stephane Eranian +# +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following +# disclaimer in the documentation and/or other materials +# provided with the distribution. +# * Neither the name of Hewlett-Packard Co. nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND +# CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +# INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS +# BE LIABLE FOR ANYDIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, +# OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR +# TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF +# THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. +# + +%.efi: %.so + $(OBJCOPY) -j .text -j .sdata -j .data -j .dynamic -j .dynsym -j .rel \ + -j .rela -j .rel.* -j .rela.* -j .rel* -j .rela* \ + -j .reloc $(FORMAT) $*.so $@ + +%.efi.debug: %.so + $(OBJCOPY) -j .debug_info -j .debug_abbrev -j .debug_aranges \ + -j .debug_line -j .debug_str -j .debug_ranges \ + -j .note.gnu.build-id \ + $(FORMAT) $*.so $@ + +%.so: %.o + $(LD) $(LDFLAGS) $^ -o $@ $(LOADLIBES) + +%.o: %.c + $(CC) $(INCDIR) $(CFLAGS) $(CPPFLAGS) -c $< -o $@ + +%.s: %.c + $(CC) $(INCDIR) $(CFLAGS) $(CPPFLAGS) -S $< -o $@ + +%.i: %.c + $(CC) $(INCDIR) $(CFLAGS) $(CPPFLAGS) -E $< -o $@ + +%.o: %.S + $(CC) $(INCDIR) $(CFLAGS) $(CPPFLAGS) -c $< -o $@ + +%.s: %.S + $(CC) $(INCDIR) $(CFLAGS) $(CPPFLAGS) -E $< -o $@ diff --git a/gnu-efi/Makefile b/gnu-efi/Makefile new file mode 100644 index 0000000..db2d830 --- /dev/null +++ b/gnu-efi/Makefile @@ -0,0 +1,129 @@ +# +# Copyright (C) 1999-2007 Hewlett-Packard Co. +# Contributed by David Mosberger +# Contributed by Stephane Eranian +# +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following +# disclaimer in the documentation and/or other materials +# provided with the distribution. +# * Neither the name of Hewlett-Packard Co. nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND +# CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +# INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS +# BE LIABLE FOR ANYDIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, +# OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR +# TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF +# THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. +# + +VERSION = 3.0.12 + +MKFILE_PATH := $(abspath $(lastword $(MAKEFILE_LIST))) +SRCDIR = $(dir $(MKFILE_PATH)) + +VPATH = $(SRCDIR) + +include $(SRCDIR)/Make.defaults + +SUBDIRS = lib gnuefi inc apps bootloader +gnuefi: lib + +all: check_gcc $(SUBDIRS) + +mkvars: + @echo AR=$(AR) + @echo ARCH=$(ARCH) + @echo ARCH3264=$(ARCH3264) + @echo AS=$(AS) + @echo ASFLAGS=$(ASFLAGS) + @echo CC=$(CC) + @echo CFLAGS=$(CFLAGS) + @echo CPPFLAGS=$(CPPFLAGS) + @echo GCCMINOR=$(GCCMINOR) + @echo GCCNEWENOUGH=$(GCCNEWENOUGH) + @echo GCCVERSION=$(GCCVERSION) + @echo HOSTARCH=$(HOSTARCH) + @echo INCDIR=$(INCDIR) + @echo INSTALL=$(INSTALL) + @echo INSTALLROOT=$(INSTALLROOT) + @echo LD=$(LD) + @echo LDFLAGS=$(LDFLAGS) + @echo LIBDIR=$(LIBDIR) + @echo OBJCOPY=$(OBJCOPY) + @echo OS=$(OS) + @echo prefix=$(prefix) + @echo PREFIX=$(PREFIX) + @echo RANLIB=$(RANLIB) + @echo SRCDIR=$(SRCDIR) + @echo TOPDIR=$(TOPDIR) + +$(SUBDIRS): + mkdir -p $(OBJDIR)/$@ + $(MAKE) -C $(OBJDIR)/$@ -f $(SRCDIR)/$@/Makefile SRCDIR=$(SRCDIR)/$@ ARCH=$(ARCH) + +clean: + rm -f *~ + @for d in $(SUBDIRS); do \ + if [ -d $(OBJDIR)/$$d ]; then \ + $(MAKE) -C $(OBJDIR)/$$d -f $(SRCDIR)/$$d/Makefile SRCDIR=$(SRCDIR)/$$d clean; \ + fi; \ + done + +install: + @for d in $(SUBDIRS); do \ + mkdir -p $(OBJDIR)/$$d; \ + $(MAKE) -C $(OBJDIR)/$$d -f $(SRCDIR)/$$d/Makefile SRCDIR=$(SRCDIR)/$$d install; done + +.PHONY: $(SUBDIRS) clean depend + +# +# on both platforms you must use gcc 3.0 or higher +# +check_gcc: +ifeq ($(GCC_VERSION),2) + @echo "you need to use a version of gcc >= 3.0, you are using `$(CC) --version`" + @exit 1 +endif + +include $(SRCDIR)/Make.rules + +test-archive: + @rm -rf /tmp/gnu-efi-$(VERSION) /tmp/gnu-efi-$(VERSION)-tmp + @mkdir -p /tmp/gnu-efi-$(VERSION)-tmp + @git archive --format=tar $(shell git branch | awk '/^*/ { print $$2 }') | ( cd /tmp/gnu-efi-$(VERSION)-tmp/ ; tar x ) + @git diff | ( cd /tmp/gnu-efi-$(VERSION)-tmp/ ; patch -s -p1 -b -z .gitdiff ) + @mv /tmp/gnu-efi-$(VERSION)-tmp/ /tmp/gnu-efi-$(VERSION)/ + @dir=$$PWD; cd /tmp; tar -c --bzip2 -f $$dir/gnu-efi-$(VERSION).tar.bz2 gnu-efi-$(VERSION) + @rm -rf /tmp/gnu-efi-$(VERSION) + @echo "The archive is in gnu-efi-$(VERSION).tar.bz2" + +tag: + git tag $(VERSION) refs/heads/master + +archive: tag + @rm -rf /tmp/gnu-efi-$(VERSION) /tmp/gnu-efi-$(VERSION)-tmp + @mkdir -p /tmp/gnu-efi-$(VERSION)-tmp + @git archive --format=tar $(VERSION) | ( cd /tmp/gnu-efi-$(VERSION)-tmp/ ; tar x ) + @mv /tmp/gnu-efi-$(VERSION)-tmp/ /tmp/gnu-efi-$(VERSION)/ + @dir=$$PWD; cd /tmp; tar -c --bzip2 -f $$dir/gnu-efi-$(VERSION).tar.bz2 gnu-efi-$(VERSION) + @rm -rf /tmp/gnu-efi-$(VERSION) + @echo "The archive is in gnu-efi-$(VERSION).tar.bz2" + diff --git a/gnu-efi/README.efilib b/gnu-efi/README.efilib new file mode 100644 index 0000000..bb857ec --- /dev/null +++ b/gnu-efi/README.efilib @@ -0,0 +1,30 @@ + +The files in the "lib" and "inc" subdirectories are using the EFI Application +Toolkit distributed by Intel at http://developer.intel.com/technology/efi + +This code is covered by the following agreement: + +Copyright (c) 1998-2000 Intel Corporation + +Redistribution and use in source and binary forms, with or without modification, are permitted +provided that the following conditions are met: + +Redistributions of source code must retain the above copyright notice, this list of conditions and +the following disclaimer. + +Redistributions in binary form must reproduce the above copyright notice, this list of conditions +and the following disclaimer in the documentation and/or other materials provided with the +distribution. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. THE EFI SPECIFICATION AND ALL OTHER INFORMATION +ON THIS WEB SITE ARE PROVIDED "AS IS" WITH NO WARRANTIES, AND ARE SUBJECT +TO CHANGE WITHOUT NOTICE. diff --git a/gnu-efi/README.elilo b/gnu-efi/README.elilo new file mode 100644 index 0000000..96a8172 --- /dev/null +++ b/gnu-efi/README.elilo @@ -0,0 +1,19 @@ + + IMPORTANT information related to the gnu-efi package + ---------------------------------------------------- + June 2001 + +As of version 3.0, the gnu-efi package is now split in two different packages: + + -> gnu-efi-X.y: contains the EFI library, include files and crt0. + + -> elilo-X.y : contains the ELILO bootloader. + +Note that X.y don't need to match for both packages. However elilo-3.x +requires at least gnu-efi-3.0. EFI support for x86_64 is provided in +gnu-efi-3.0d. + +Both packages can be downloaded from: + + http://www.sf.net/projects/gnu-efi + http://www.sf.net/projects/elilo diff --git a/gnu-efi/README.git b/gnu-efi/README.git new file mode 100644 index 0000000..c719b20 --- /dev/null +++ b/gnu-efi/README.git @@ -0,0 +1,21 @@ +README.git + +Generating releases from git a very simple process; + +1) Edit the file "Makefile". Changing the "VERSION" line to the new version. +2) Do a "git commit" just for the version number change. +3) Then do a "make test-archive". +That will make a file in the current directory gnu-efi-$VERSION.tar.bz2 , +with its top level directory gnu-efi-$VERSION/ and the source tree under that. + +Once you've tested that and you're sure it's what you want to release, +4) Do "make archive", which will tag a release in git and generate a +final tarball from it. + +You then push to the archive, being sure to include the tag: +5) "git push origin master:master --tags" + +And upload the archive wherever it's supposed to go. + + + diff --git a/gnu-efi/README.gnuefi b/gnu-efi/README.gnuefi new file mode 100644 index 0000000..512698c --- /dev/null +++ b/gnu-efi/README.gnuefi @@ -0,0 +1,405 @@ + ------------------------------------------------- + Building EFI Applications Using the GNU Toolchain + ------------------------------------------------- + + David Mosberger + + 23 September 1999 + + + Copyright (c) 1999-2007 Hewlett-Packard Co. + Copyright (c) 2006-2010 Intel Co. + +Last update: 04/09/2007 + +* Introduction + +This document has two parts: the first part describes how to develop +EFI applications for IA-64,x86 and x86_64 using the GNU toolchain and the EFI +development environment contained in this directory. The second part +describes some of the more subtle aspects of how this development +environment works. + + + +* Part 1: Developing EFI Applications + + +** Prerequisites: + + To develop x86 and x86_64 EFI applications, the following tools are needed: + + - gcc-3.0 or newer (gcc 2.7.2 is NOT sufficient!) + As of gnu-efi-3.0b, the Redhat 8.0 toolchain is known to work, + but the Redhat 9.0 toolchain is not currently supported. + + - A version of "objcopy" that supports EFI applications. To + check if your version includes EFI support, issue the + command: + + objcopy --help + + Verify that the line "supported targets" contains the string + "efi-app-ia32" and "efi-app-x86_64" and that the "-j" option + accepts wildcards. The binutils release binutils-2.24 + supports Intel64 EFI and accepts wildcard section names. + + - For debugging purposes, it's useful to have a version of + "objdump" that supports EFI applications as well. This + allows inspect and disassemble EFI binaries. + + To develop IA-64 EFI applications, the following tools are needed: + + - A version of gcc newer than July 30th 1999 (older versions + had problems with generating position independent code). + As of gnu-efi-3.0b, gcc-3.1 is known to work well. + + - A version of "objcopy" that supports EFI applications. To + check if your version includes EFI support, issue the + command: + + objcopy --help + + Verify that the line "supported targets" contains the string + "efi-app-ia64" and that the "-j" option accepts wildcards. + + - For debugging purposes, it's useful to have a version of + "objdump" that supports EFI applications as well. This + allows inspect and disassemble EFI binaries. + + +** Directory Structure + +This EFI development environment contains the following +subdirectories: + + inc: This directory contains the EFI-related include files. The + files are taken from Intel's EFI source distribution, except + that various fixes were applied to make it compile with the + GNU toolchain. + + lib: This directory contains the source code for Intel's EFI library. + Again, the files are taken from Intel's EFI source + distribution, with changes to make them compile with the GNU + toolchain. + + gnuefi: This directory contains the glue necessary to convert ELF64 + binaries to EFI binaries. Various runtime code bits, such as + a self-relocator are included as well. This code has been + contributed by the Hewlett-Packard Company and is distributed + under the GNU GPL. + + apps: This directory contains a few simple EFI test apps. + +** Setup + +It is necessary to edit the Makefile in the directory containing this +README file before EFI applications can be built. Specifically, you +should verify that macros CC, AS, LD, AR, RANLIB, and OBJCOPY point to +the appropriate compiler, assembler, linker, ar, and ranlib binaries, +respectively. + +If you're working in a cross-development environment, be sure to set +macro ARCH to the desired target architecture ("ia32" for x86, "x86_64" for +x86_64 and "ia64" for IA-64). For convenience, this can also be done from +the make command line (e.g., "make ARCH=ia64"). + + +** Building + +To build the sample EFI applications provided in subdirectory "apps", +simply invoke "make" in the toplevel directory (the directory +containing this README file). This should build lib/libefi.a and +gnuefi/libgnuefi.a first and then all the EFI applications such as a +apps/t6.efi. + + +** Running + +Just copy the EFI application (e.g., apps/t6.efi) to the EFI +filesystem, boot EFI, and then select "Invoke EFI application" to run +the application you want to test. Alternatively, you can invoke the +Intel-provided "nshell" application and then invoke your test binary +via the command line interface that "nshell" provides. + + +** Writing Your Own EFI Application + +Suppose you have your own EFI application in a file called +"apps/myefiapp.c". To get this application built by the GNU EFI build +environment, simply add "myefiapp.efi" to macro TARGETS in +apps/Makefile. Once this is done, invoke "make" in the top level +directory. This should result in EFI application apps/myefiapp.efi, +ready for execution. + +The GNU EFI build environment allows to write EFI applications as +described in Intel's EFI documentation, except for two differences: + + - The EFI application's entry point is always called "efi_main". The + declaration of this routine is: + + EFI_STATUS efi_main (EFI_HANDLE image, EFI_SYSTEM_TABLE *systab); + + - UNICODE string literals must be written as W2U(L"Sample String") + instead of just L"Sample String". The W2U() macro is defined in + . This header file also declares the function W2UCpy() + which allows to convert a wide string into a UNICODE string and + store the result in a programmer-supplied buffer. + + - Calls to EFI services should be made via uefi_call_wrapper(). This + ensures appropriate parameter passing for the architecture. + + +* Part 2: Inner Workings + +WARNING: This part contains all the gory detail of how the GNU EFI +toolchain works. Normal users do not have to worry about such +details. Reading this part incurs a definite risk of inducing severe +headaches or other maladies. + +The basic idea behind the GNU EFI build environment is to use the GNU +toolchain to build a normal ELF binary that, at the end, is converted +to an EFI binary. EFI binaries are really just PE32+ binaries. PE +stands for "Portable Executable" and is the object file format +Microsoft is using on its Windows platforms. PE is basically the COFF +object file format with an MS-DOS2.0 compatible header slapped on in +front of it. The "32" in PE32+ stands for 32 bits, meaning that PE32 +is a 32-bit object file format. The plus in "PE32+" indicates that +this format has been hacked to allow loading a 4GB binary anywhere in +a 64-bit address space (unlike ELF64, however, this is not a full +64-bit object file format because the entire binary cannot span more +than 4GB of address space). EFI binaries are plain PE32+ binaries +except that the "subsystem id" differs from normal Windows binaries. +There are two flavors of EFI binaries: "applications" and "drivers" +and each has there own subsystem id and are identical otherwise. At +present, the GNU EFI build environment supports the building of EFI +applications only, though it would be trivial to generate drivers, as +the only difference is the subsystem id. For more details on PE32+, +see the spec at + + http://msdn.microsoft.com/library/specs/msdn_pecoff.htm. + +In theory, converting a suitable ELF64 binary to PE32+ is easy and +could be accomplished with the "objcopy" utility by specifying option +--target=efi-app-ia32 (x86) or --target=efi-app-ia64 (IA-64). But +life never is that easy, so here some complicating factors: + + (1) COFF sections are very different from ELF sections. + + ELF binaries distinguish between program headers and sections. + The program headers describe the memory segments that need to + be loaded/initialized, whereas the sections describe what + constitutes those segments. In COFF (and therefore PE32+) no + such distinction is made. Thus, COFF sections need to be page + aligned and have a size that is a multiple of the page size + (4KB for EFI), whereas ELF allows sections at arbitrary + addresses and with arbitrary sizes. + + (2) EFI binaries should be relocatable. + + Since EFI binaries are executed in physical mode, EFI cannot + guarantee that a given binary can be loaded at its preferred + address. EFI does _try_ to load a binary at it's preferred + address, but if it can't do so, it will load it at another + address and then relocate the binary using the contents of the + .reloc section. + + (3) On IA-64, the EFI entry point needs to point to a function + descriptor, not to the code address of the entry point. + + (4) The EFI specification assumes that wide characters use UNICODE + encoding. + + ANSI C does not specify the size or encoding that a wide + character uses. These choices are "implementation defined". + On most UNIX systems, the GNU toolchain uses a wchar_t that is + 4 bytes in size. The encoding used for such characters is + (mostly) UCS4. + +In the following sections, we address how the GNU EFI build +environment addresses each of these issues. + + +** (1) Accommodating COFF Sections + +In order to satisfy the COFF constraint of page-sized and page-aligned +sections, the GNU EFI build environment uses the special linker script +in gnuefi/elf_$(ARCH)_efi.lds where $(ARCH) is the target architecture +("ia32" for x86, "x86_64" for x86_64 and "ia64" for IA-64). +This script is set up to create only eight COFF section, each page aligned +and page sized.These eight sections are used to group together the much +greater number of sections that are typically present in ELF object files. +Specifically: + + .hash (and/or .gnu.hash) + Collects the ELF .hash info (this section _must_ be the first + section in order to build a shared object file; the section is + not actually loaded or used at runtime). + + GNU binutils provides a mechanism to generate different hash info + via --hash-style= option. In this case output + shared object will contain .hash section, .gnu.hash section or + both. In order to generate correct output linker script preserves + both types of hash sections. + + .text + Collects all sections containing executable code. + + .data + Collects read-only and read-write data, literal string data, + global offset tables, the uninitialized data segment (bss) and + various other sections containing data. + + The reason read-only data is placed here instead of the in + .text is to make it possible to disassemble the .text section + without getting garbage due to read-only data. Besides, since + EFI binaries execute in physical mode, differences in page + protection do not matter. + + The reason the uninitialized data is placed in this section is + that the EFI loader appears to be unable to handle sections + that are allocated but not loaded from the binary. + + .dynamic, .dynsym, .rela, .rel, .reloc + These sections contains the dynamic information necessary to + self-relocate the binary (see below). + +A couple of more points worth noting about the linker script: + + o On IA-64, the global pointer symbol (__gp) needs to be placed such + that the _entire_ EFI binary can be addressed using the signed + 22-bit offset that the "addl" instruction affords. Specifically, + this means that __gp should be placed at ImageBase + 0x200000. + Strictly speaking, only a couple of symbols need to be addressable + in this fashion, so with some care it should be possible to build + binaries much larger than 4MB. To get a list of symbols that need + to be addressable in this fashion, grep the assembly files in + directory gnuefi for the string "@gprel". + + o The link address (ImageBase) of the binary is (arbitrarily) set to + zero. This could be set to something larger to increase the chance + of EFI being able to load the binary without requiring relocation. + However, a start address of 0 makes debugging a wee bit easier + (great for those of us who can add, but not subtract... ;-). + + o The relocation related sections (.dynamic, .rel, .rela, .reloc) + cannot be placed inside .data because some tools in the GNU + toolchain rely on the existence of these sections. + + o Some sections in the ELF binary intentionally get dropped when + building the EFI binary. Particularly noteworthy are the dynamic + relocation sections for the .plabel and .reloc sections. It would + be _wrong_ to include these sections in the EFI binary because it + would result in .reloc and .plabel being relocated twice (once by + the EFI loader and once by the self-relocator; see below for a + description of the latter). Specifically, only the sections + mentioned with the -j option in the final "objcopy" command are + retained in the EFI binary (see Make.rules). + + +** (2) Building Relocatable Binaries + +ELF binaries are normally linked for a fixed load address and are thus +not relocatable. The only kind of ELF object that is relocatable are +shared objects ("shared libraries"). However, even those objects are +usually not completely position independent and therefore require +runtime relocation by the dynamic loader. For example, IA-64 binaries +normally require relocation of the global offset table. + +The approach to building relocatable binaries in the GNU EFI build +environment is to: + + (a) build an ELF shared object + + (b) link it together with a self-relocator that takes care of + applying the dynamic relocations that may be present in the + ELF shared object + + (c) convert the resulting image to an EFI binary + +The self-relocator is of course architecture dependent. The x86 +version can be found in gnuefi/reloc_ia32.c, the x86_64 version +can be found in gnuefi/reloc_x86_64.c and the IA-64 version can be +found in gnuefi/reloc_ia64.S. + +The self-relocator operates as follows: the startup code invokes it +right after EFI has handed off control to the EFI binary at symbol +"_start". Upon activation, the self-relocator searches the .dynamic +section (whose starting address is given by symbol _DYNAMIC) for the +dynamic relocation information, which can be found in the DT_REL, +DT_RELSZ, and DT_RELENT entries of the dynamic table (DT_RELA, +DT_RELASZ, and DT_RELAENT in the case of rela relocations, as is the +case for IA-64). The dynamic relocation information points to the ELF +relocation table. Once this table is found, the self-relocator walks +through it, applying each relocation one by one. Since the EFI +binaries are fully resolved shared objects, only a subset of all +possible relocations need to be supported. Specifically, on x86 only +the R_386_RELATIVE relocation is needed. On IA-64, the relocations +R_IA64_DIR64LSB, R_IA64_REL64LSB, and R_IA64_FPTR64LSB are needed. +Note that the R_IA64_FPTR64LSB relocation requires access to the +dynamic symbol table. This is why the .dynsym section is included in +the EFI binary. Another complication is that this relocation requires +memory to hold the function descriptors (aka "procedure labels" or +"plabels"). Each function descriptor uses 16 bytes of memory. The +IA-64 self-relocator currently reserves a static memory area that can +hold 100 of these descriptors. If the self-relocator runs out of +space, it causes the EFI binary to fail with error code 5 +(EFI_BUFFER_TOO_SMALL). When this happens, the manifest constant +MAX_FUNCTION_DESCRIPTORS in gnuefi/reloc_ia64.S should be increased +and the application recompiled. An easy way to count the number of +function descriptors required by an EFI application is to run the +command: + + objdump --dynamic-reloc example.so | fgrep FPTR64 | wc -l + +assuming "example" is the name of the desired EFI application. + + +** (3) Creating the Function Descriptor for the IA-64 EFI Binaries + +As mentioned above, the IA-64 PE32+ format assumes that the entry +point of the binary is a function descriptor. A function descriptors +consists of two double words: the first one is the code entry point +and the second is the global pointer that should be loaded before +calling the entry point. Since the ELF toolchain doesn't know how to +generate a function descriptor for the entry point, the startup code +in gnuefi/crt0-efi-ia64.S crafts one manually by with the code: + + .section .plabel, "a" + _start_plabel: + data8 _start + data8 __gp + +this places the procedure label for entry point _start in a section +called ".plabel". Now, the only problem is that _start and __gp need +to be relocated _before_ EFI hands control over to the EFI binary. +Fortunately, PE32+ defines a section called ".reloc" that can achieve +this. Thus, in addition to manually crafting the function descriptor, +the startup code also crafts a ".reloc" section that has will cause +the EFI loader to relocate the function descriptor before handing over +control to the EFI binary (again, see the PECOFF spec mentioned above +for details). + +A final question may be why .plabel and .reloc need to go in their own +COFF sections. The answer is simply: we need to be able to discard +the relocation entries that are generated for these sections. By +placing them in these sections, the relocations end up in sections +".rela.plabel" and ".rela.reloc" which makes it easy to filter them +out in the filter script. Also, the ".reloc" section needs to be in +its own section so that the objcopy program can recognize it and can +create the correct directory entries in the PE32+ binary. + + +** (4) Convenient and Portable Generation of UNICODE String Literals + +As of gnu-efi-3.0, we make use (and somewhat abuse) the gcc option +that forces wide characters (WCHAR_T) to use short integers (2 bytes) +instead of integers (4 bytes). This way we match the Unicode character +size. By abuse, we mean that we rely on the fact that the regular ASCII +characters are encoded the same way between (short) wide characters +and Unicode and basically only use the first byte. This allows us +to just use them interchangeably. + +The gcc option to force short wide characters is : -fshort-wchar + + * * * The End * * * diff --git a/gnu-efi/apps/AllocPages.c b/gnu-efi/apps/AllocPages.c new file mode 100644 index 0000000..bb81849 --- /dev/null +++ b/gnu-efi/apps/AllocPages.c @@ -0,0 +1,184 @@ + +/* + * Copyright (C) 2013 Jerry Hoemann + * + * + * Application to allocate memory at EFI. Syntax of command + * mimics the EFI Boot Service "AllocatePages." + * + * See UEFI spec 2.3, Section 6.2. + * + * + + + + +FS1:\> memmap +Type Start End #pages Attributes +BS_Code 0000000000000000-0000000000000FFF 0000000000000001 000000000000000F +Available 0000000000001000-000000000008DFFF 000000000000008D 000000000000000F +Reserved 000000000008E000-000000000008FFFF 0000000000000002 000000000000000F +Available 0000000000090000-000000000009FFFF 0000000000000010 000000000000000F +Available 0000000000100000-000000000FFFFFFF 000000000000FF00 000000000000000F +BS_Code 0000000010000000-0000000010061FFF 0000000000000062 000000000000000F +Available 0000000010062000-000000005CDFFFFF 000000000004CD9E 000000000000000F +ACPI_NVS 000000005CE00000-000000005DDFFFFF 0000000000001000 000000000000000F +BS_Data 000000005DE00000-000000005DFFFFFF 0000000000000200 000000000000000F +Available 000000005E000000-000000005EF1CFFF 0000000000000F1D 000000000000000F +BS_Data 000000005EF1D000-00000000709FBFFF 0000000000011ADF 000000000000000F +Available 00000000709FC000-00000000710E3FFF 00000000000006E8 000000000000000F +LoaderCode 00000000710E4000-00000000711FEFFF 000000000000011B 000000000000000F +Available 00000000711FF000-0000000071901FFF 0000000000000703 000000000000000F +BS_Code 0000000071902000-00000000721FEFFF 00000000000008FD 000000000000000F + + +Example to allocat 5 pages type BootCode at address 20000000 (hex) + + +FS1:\> AllocPages.efi 2 3 5 20000000 +AllocatePage: __AllocType__ __MemType__ __NumPages__ [__Addr__] +__AllocType__ {0,1,2} -- Any, MaxAddr, Addr +__MemType__ {0..13}, Reserved ==0, LCode==1, LData==2, BSCode==3, BSData==4, ... +__NumPages__ {0..F000000} +[__Addr__] 0... 3FFFFFFFFFFF +All numbers in hex no leading 0x + +AllocatPage(2,3,5,20000000) + + +Example to allocat 5 pages type BootCode at address 30000000 (hex) + + +FS1:\> AllocPages.efi 2 3 5 30000000 +AllocatePage: __AllocType__ __MemType__ __NumPages__ [__Addr__] +__AllocType__ {0,1,2} -- Any, MaxAddr, Addr +__MemType__ {0..13}, Reserved ==0, LCode==1, LData==2, BSCode==3, BSData==4, ... +__NumPages__ {0..F000000} +[__Addr__] 0... 3FFFFFFFFFFF +All numbers in hex no leading 0x + + + +FS1:\> memmap +Type Start End #pages Attributes +BS_Code 0000000000000000-0000000000000FFF 0000000000000001 000000000000000F +Available 0000000000001000-000000000008DFFF 000000000000008D 000000000000000F +Reserved 000000000008E000-000000000008FFFF 0000000000000002 000000000000000F +Available 0000000000090000-000000000009FFFF 0000000000000010 000000000000000F +Available 0000000000100000-000000000FFFFFFF 000000000000FF00 000000000000000F +BS_Code 0000000010000000-0000000010061FFF 0000000000000062 000000000000000F +Available 0000000010062000-000000001FFFFFFF 000000000000FF9E 000000000000000F +BS_Code 0000000020000000-0000000020004FFF 0000000000000005 000000000000000F +Available 0000000020005000-000000002FFFFFFF 000000000000FFFB 000000000000000F +BS_Code 0000000030000000-0000000030004FFF 0000000000000005 000000000000000F +Available 0000000030005000-000000005CDFFFFF 000000000002CDFB 000000000000000F +ACPI_NVS 000000005CE00000-000000005DDFFFFF 0000000000001000 000000000000000F +BS_Data 000000005DE00000-000000005DFFFFFF 0000000000000200 000000000000000F +Available 000000005E000000-000000005EF1CFFF 0000000000000F1D 000000000000000F +BS_Data 000000005EF1D000-00000000709FBFFF 0000000000011ADF 000000000000000F +Available 00000000709FC000-00000000710E3FFF 00000000000006E8 000000000000000F +LoaderCode 00000000710E4000-00000000711FEFFF 000000000000011B 000000000000000F +Available 00000000711FF000-0000000071901FFF 0000000000000703 000000000000000F +BS_Code 0000000071902000-00000000721FEFFF 00000000000008FD 000000000000000F + + + + + + */ + +#include +#include + + +#define MAX_NUM_PAGES 0x000000000F000000 +#define MAX_ADDR ((1ULL << 46) - 1) + + +#ifdef DEBUG +#undef DEBUG +#endif +#define DEBUG 0 + + + +EFI_STATUS +efi_main (EFI_HANDLE image, EFI_SYSTEM_TABLE *systab) +{ + + EFI_STATUS efi_status; + CHAR16 **argv; + INTN argc; + INTN err = 0; +#if DEBUG + INTN c = 0; +#endif + INTN AllocType = -1; + INTN MemType = -1; + INTN NumPages = -1; + EFI_PHYSICAL_ADDRESS Addr = 0; + + InitializeLib(image, systab); + + Print(L"AllocatePage: __AllocType__ __MemType__ __NumPages__ [__Addr__]\n"); + Print(L"__AllocType__ {0,1,2} -- Any, MaxAddr, Addr\n"); + Print(L"__MemType__ {0..13}, Reserved ==0, LCode==1, LData==2, BSCode==3, BSData==4, ...\n"); + Print(L"__NumPages__ {0..%x}\n", MAX_NUM_PAGES); + Print(L"[__Addr__] 0... %llx\n", MAX_ADDR); + Print(L"All numbers in hex no leading 0x\n"); + Print(L"\n"); + +#if DEBUG + Print(L"Now get argc/argv\n"); +#endif + argc = GetShellArgcArgv(image, &argv); +#if DEBUG + Print(L"argc = %d\n", argc); +#endif + +#if DEBUG + for (c = 0; c < argc; c++ ) { + Print(L"argv[%d] = <%s>\n", c, argv[c]); + } +#endif + if ( (argc < 4) || (argc > 5) ) { + Print(L"Wrong argument count\n"); + return EFI_SUCCESS; + } + + AllocType = xtoi(argv[1]); + MemType = xtoi(argv[2]); + NumPages = xtoi(argv[3]); + if ( argc == 5 ) Addr = xtoi(argv[4]); + + if ( (AllocType < 0) || (AllocType > 2)) { + Print(L"Invalid AllocType\n"); + err++; + } + if ( (MemType < 0) || (MemType > 13) ) { + Print(L"Invalid MemType\n"); + err++; + } + if ( (NumPages < 0) || (NumPages > MAX_NUM_PAGES) ) { + Print(L"Inavlid NumPages\n"); + err++; + } + if ( Addr > MAX_ADDR ) { + Print(L"Inavlid Address\n"); + err++; + } + if ( err ) { + return EFI_INVALID_PARAMETER; + } + + Print(L"AllocatPage(%d,%d,%d,%lx)\n", AllocType, MemType, NumPages, Addr); + + efi_status = uefi_call_wrapper(BS->AllocatePages, 4, AllocType, MemType, NumPages, &Addr); + + if ( EFI_ERROR(efi_status) ) { + Print(L"Allocate Pages Failed: %d\n", efi_status); + return efi_status; + } + + return EFI_SUCCESS; +} diff --git a/gnu-efi/apps/FreePages.c b/gnu-efi/apps/FreePages.c new file mode 100644 index 0000000..247c75d --- /dev/null +++ b/gnu-efi/apps/FreePages.c @@ -0,0 +1,145 @@ + + +/* + * Copyright (C) 2013 Jerry Hoemann + * + * Application to allocate memory at EFI. Syntax of command + * mimics the EFI Boot Service "FreePages." + * + * See UEFI spec 2.3, Section 6.2. + * + +Example freeing a 5 page BS_Code setment at address: 0000000020000000 (hex) + + +FS1:\> memmap +Type Start End #pages Attributes +BS_Code 0000000000000000-0000000000000FFF 0000000000000001 000000000000000F +Available 0000000000001000-000000000008DFFF 000000000000008D 000000000000000F +Reserved 000000000008E000-000000000008FFFF 0000000000000002 000000000000000F +Available 0000000000090000-000000000009FFFF 0000000000000010 000000000000000F +Available 0000000000100000-000000000FFFFFFF 000000000000FF00 000000000000000F +BS_Code 0000000010000000-0000000010061FFF 0000000000000062 000000000000000F +Available 0000000010062000-000000001FFFFFFF 000000000000FF9E 000000000000000F +BS_Code 0000000020000000-0000000020004FFF 0000000000000005 000000000000000F +Available 0000000020005000-000000005DDFFFFF 000000000003DDFB 000000000000000F +BS_Data 000000005DE00000-000000005DFFFFFF 0000000000000200 000000000000000F +Available 000000005E000000-000000006DE7CFFF 000000000000FE7D 000000000000000F +ACPI_NVS 000000006DE7D000-000000006EE7CFFF 0000000000001000 000000000000000F +BS_Data 000000006EE7D000-00000000709FBFFF 0000000000001B7F 000000000000000F +Available 00000000709FC000-00000000710E3FFF 00000000000006E8 000000000000000F + + +FS1:\> FreePages 0000000020000000 5 +FreePages: __PhysAddr__ __PgCnt__ +__PhysAddr__ 0... 3FFFFFFFFFFF +__PgCnt__ [0..F000000] +All numbers hex w/ no leading 0x + +FreePages(20000000,5) + + + +FS1:\> memmap +Type Start End #pages Attributes +BS_Code 0000000000000000-0000000000000FFF 0000000000000001 000000000000000F +Available 0000000000001000-000000000008DFFF 000000000000008D 000000000000000F +Reserved 000000000008E000-000000000008FFFF 0000000000000002 000000000000000F +Available 0000000000090000-000000000009FFFF 0000000000000010 000000000000000F +Available 0000000000100000-000000000FFFFFFF 000000000000FF00 000000000000000F +BS_Code 0000000010000000-0000000010061FFF 0000000000000062 000000000000000F +Available 0000000010062000-000000005DDFFFFF 000000000004DD9E 000000000000000F +BS_Data 000000005DE00000-000000005DFFFFFF 0000000000000200 000000000000000F +Available 000000005E000000-000000006DE7CFFF 000000000000FE7D 000000000000000F +ACPI_NVS 000000006DE7D000-000000006EE7CFFF 0000000000001000 000000000000000F +BS_Data 000000006EE7D000-00000000709FBFFF 0000000000001B7F 000000000000000F +Available 00000000709FC000-00000000710E3FFF 00000000000006E8 000000000000000F + + + */ + +#include +#include + +/* + * FreePages: __PhysAddr__ __PgCnt__ + * + */ + +#define MAX_NUM_PAGES 0x000000000F000000 + +#define MAX_ADDR ((1ULL << 46) - 1) + +#ifdef DEBUG +#undef DEBUG +#endif +#define DEBUG 0 + + +EFI_STATUS +efi_main (EFI_HANDLE image, EFI_SYSTEM_TABLE *systab) +{ + + EFI_STATUS efi_status; + CHAR16 **argv; + INTN argc = 0; +#if DEBUG + INTN c = 0; +#endif + INTN err = 0; + + INTN PgCnt = -1; + EFI_PHYSICAL_ADDRESS PhysAddr = 0; + + InitializeLib(image, systab); + + Print(L"FreePages: __PhysAddr__ __PgCnt__\n"); + Print(L"__PhysAddr__ 0... %llx\n", MAX_ADDR); + Print(L"__PgCnt__ [0..%lx]\n", MAX_NUM_PAGES); + Print(L"All numbers hex w/ no leading 0x\n"); + Print(L"\n"); + +#if DEBUG + Print(L"Now parse argc/argv\n"); +#endif + argc = GetShellArgcArgv(image, &argv); +#if DEBUG + Print(L"argc = %d\n", argc); +#endif + +#if DEBUG + for (c = 0; c < argc; c++ ) { + Print(L"argv[%d] = <%s>\n", c, argv[c]); + } +#endif + if (argc != 3) { + Print(L"Invalid argument count\n"); + return EFI_SUCCESS; + } + + PhysAddr = xtoi(argv[1]); + PgCnt = xtoi(argv[2]); + + if ( (PgCnt < 0) || (PgCnt > MAX_NUM_PAGES) ) { + Print(L"Inavlid PgCnt\n"); + err++; + } + if ( PhysAddr > MAX_ADDR ) { + Print(L"Inavlid Address\n"); + err++; + } + if ( err ) { + return EFI_SUCCESS; + } + + Print(L"FreePages(%lx,%d)\n", PhysAddr, PgCnt); + + efi_status = uefi_call_wrapper(BS->FreePages, 2, PhysAddr, PgCnt); + + if ( EFI_ERROR(efi_status) ) { + Print(L"Free Pages Failed: %d\n", efi_status); + return efi_status; + } + + return EFI_SUCCESS; +} diff --git a/gnu-efi/apps/Makefile b/gnu-efi/apps/Makefile new file mode 100644 index 0000000..4e1b69a --- /dev/null +++ b/gnu-efi/apps/Makefile @@ -0,0 +1,95 @@ +# +# Copyright (C) 1999-2001 Hewlett-Packard Co. +# Contributed by David Mosberger +# Contributed by Stephane Eranian +# +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following +# disclaimer in the documentation and/or other materials +# provided with the distribution. +# * Neither the name of Hewlett-Packard Co. nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND +# CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +# INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS +# BE LIABLE FOR ANYDIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, +# OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR +# TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF +# THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. +# + +SRCDIR = . + +VPATH = $(SRCDIR) + +include $(SRCDIR)/../Make.defaults + +TOPDIR = $(SRCDIR)/.. + +CDIR=$(TOPDIR)/.. +LINUX_HEADERS = /usr/src/sys/build +CPPFLAGS += -D__KERNEL__ -I$(LINUX_HEADERS)/include +CRTOBJS = ../gnuefi/crt0-efi-$(ARCH).o + +LDSCRIPT = $(TOPDIR)/gnuefi/elf_$(ARCH)_efi.lds +ifneq (,$(findstring FreeBSD,$(OS))) +LDSCRIPT = $(TOPDIR)/gnuefi/elf_$(ARCH)_fbsd_efi.lds +endif + +LDFLAGS += -shared -Bsymbolic -L../lib -L../gnuefi $(CRTOBJS) + +LOADLIBES += -lefi -lgnuefi +LOADLIBES += $(LIBGCC) +LOADLIBES += -T $(LDSCRIPT) + +TARGET_APPS = t.efi t2.efi t3.efi t4.efi t5.efi t6.efi \ + printenv.efi t7.efi t8.efi tcc.efi modelist.efi \ + route80h.efi drv0_use.efi AllocPages.efi exit.efi \ + FreePages.efi setjmp.efi debughook.efi debughook.efi.debug \ + bltgrid.efi lfbgrid.efi setdbg.efi unsetdbg.efi +TARGET_BSDRIVERS = drv0.efi +TARGET_RTDRIVERS = + +ifneq ($(HAVE_EFI_OBJCOPY),) + +FORMAT := --target efi-app-$(ARCH) +$(TARGET_BSDRIVERS): FORMAT=--target efi-bsdrv-$(ARCH) +$(TARGET_RTDRIVERS): FORMAT=--target efi-rtdrv-$(ARCH) + +else + +SUBSYSTEM := 0xa +$(TARGET_BSDRIVERS): SUBSYSTEM = 0xb +$(TARGET_RTDRIVERS): SUBSYSTEM = 0xc + +FORMAT := -O binary +LDFLAGS += --defsym=EFI_SUBSYSTEM=$(SUBSYSTEM) + +endif + +TARGETS = $(TARGET_APPS) $(TARGET_BSDRIVERS) $(TARGET_RTDRIVERS) + +all: $(TARGETS) + +clean: + rm -f $(TARGETS) *~ *.o *.so + +.PHONY: install + +include $(SRCDIR)/../Make.rules diff --git a/gnu-efi/apps/bltgrid.c b/gnu-efi/apps/bltgrid.c new file mode 100644 index 0000000..2adde6a --- /dev/null +++ b/gnu-efi/apps/bltgrid.c @@ -0,0 +1,131 @@ +#include +#include + +extern EFI_GUID GraphicsOutputProtocol; + +static void +fill_boxes(UINT32 *PixelBuffer, UINT32 Width, UINT32 Height) +{ + UINT32 y, x = 0; + /* + * This assums BGRR, but it doesn't really matter; we pick red and + * green so it'll just be blue/green if the pixel format is backwards. + */ + EFI_GRAPHICS_OUTPUT_BLT_PIXEL Red = {0, 0, 0xff, 0}, + Green = {0, 0xff, 0, 0}, + *Color; + + for (y = 0; y < Height; y++) { + Color = ((y / 32) % 2 == 0) ? &Red : &Green; + for (x = 0; x < Width; x++) { + if (x % 32 == 0 && x != 0) + Color = (Color == &Red) ? &Green : &Red; + PixelBuffer[y * Width + x] = *(UINT32 *)Color; + } + } +} + +static void +draw_boxes(EFI_GRAPHICS_OUTPUT_PROTOCOL *gop) +{ + int i, imax; + EFI_STATUS rc; + EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *info; + UINTN NumPixels; + UINT32 *PixelBuffer; + UINT32 BufferSize; + + if (gop->Mode) { + imax = gop->Mode->MaxMode; + } else { + Print(L"gop->Mode is NULL\n"); + return; + } + + for (i = 0; i < imax; i++) { + UINTN SizeOfInfo; + rc = uefi_call_wrapper(gop->QueryMode, 4, gop, i, &SizeOfInfo, + &info); + if (EFI_ERROR(rc) && rc == EFI_NOT_STARTED) { + Print(L"gop->QueryMode() returned %r\n", rc); + Print(L"Trying to start GOP with SetMode().\n"); + rc = uefi_call_wrapper(gop->SetMode, 2, gop, + gop->Mode ? gop->Mode->Mode : 0); + rc = uefi_call_wrapper(gop->QueryMode, 4, gop, i, + &SizeOfInfo, &info); + } + + if (EFI_ERROR(rc)) { + Print(L"%d: Bad response from QueryMode: %r (%d)\n", + i, rc, rc); + continue; + } + + if (CompareMem(info, gop->Mode->Info, sizeof (*info))) + continue; + + NumPixels = info->VerticalResolution * info->HorizontalResolution; + BufferSize = NumPixels * sizeof(UINT32); + + PixelBuffer = AllocatePool(BufferSize); + if (!PixelBuffer) { + Print(L"Allocation of 0x%08lx bytes failed.\n", + sizeof(UINT32) * NumPixels); + return; + } + + fill_boxes(PixelBuffer, + info->HorizontalResolution, info->VerticalResolution); + + uefi_call_wrapper(gop->Blt, 10, gop, + (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *)PixelBuffer, + EfiBltBufferToVideo, + 0, 0, 0, 0, + info->HorizontalResolution, + info->VerticalResolution, + 0); + return; + } + Print(L"Never found the active video mode?\n"); +} + +static EFI_STATUS +SetWatchdog(UINTN seconds) +{ + EFI_STATUS rc; + rc = uefi_call_wrapper(BS->SetWatchdogTimer, 4, seconds, 0x1ffff, + 0, NULL); + if (EFI_ERROR(rc)) { + CHAR16 Buffer[64]; + StatusToString(Buffer, rc); + Print(L"Bad response from QueryMode: %s (%d)\n", Buffer, rc); + } + return rc; +} + +EFI_STATUS +efi_main (EFI_HANDLE image_handle, EFI_SYSTEM_TABLE *systab) +{ + EFI_STATUS rc; + EFI_GRAPHICS_OUTPUT_PROTOCOL *gop; + + InitializeLib(image_handle, systab); + + SetWatchdog(10); + + rc = LibLocateProtocol(&GraphicsOutputProtocol, (void **)&gop); + if (EFI_ERROR(rc)) { + Print(L"Could not locate GOP: %r\n", rc); + return rc; + } + + if (!gop) { + Print(L"LocateProtocol(GOP, &gop) returned %r but GOP is NULL\n", rc); + return EFI_UNSUPPORTED; + } + + draw_boxes(gop); + + SetWatchdog(0); + return EFI_SUCCESS; +} diff --git a/gnu-efi/apps/debughook.c b/gnu-efi/apps/debughook.c new file mode 100644 index 0000000..78e4a76 --- /dev/null +++ b/gnu-efi/apps/debughook.c @@ -0,0 +1,97 @@ +#include +#include + +EFI_STATUS +GetVariableAttr(CHAR16 *var, UINT8 **data, UINTN *len, EFI_GUID owner, + UINT32 *attributes) +{ + EFI_STATUS efi_status; + + *len = 0; + + efi_status = uefi_call_wrapper(RT->GetVariable, 5, var, &owner, + NULL, len, NULL); + if (efi_status != EFI_BUFFER_TOO_SMALL) + return efi_status; + + *data = AllocateZeroPool(*len); + if (!*data) + return EFI_OUT_OF_RESOURCES; + + efi_status = uefi_call_wrapper(RT->GetVariable, 5, var, &owner, + attributes, len, *data); + + if (efi_status != EFI_SUCCESS) { + FreePool(*data); + *data = NULL; + } + return efi_status; +} + +EFI_STATUS +GetVariable(CHAR16 *var, UINT8 **data, UINTN *len, EFI_GUID owner) +{ + return GetVariableAttr(var, data, len, owner, NULL); +} + +EFI_GUID DUMMY_GUID = +{0x55aad538, 0x8f82, 0x4e2a, {0xa4,0xf0,0xbe, 0x59, 0x13, 0xb6, 0x5f, 0x1e}}; + +#if defined(__clang__) +# define _OPTNONE __attribute__((optnone)) +#else +# define _OPTNONE __attribute__((__optimize__("0"))) +#endif + +static _OPTNONE void +DebugHook(void) +{ + EFI_GUID guid = DUMMY_GUID; + UINT8 *data = NULL; + UINTN dataSize = 0; + EFI_STATUS efi_status; + register volatile unsigned long long x = 0; + extern char _text, _data; + + if (x) + return; + + efi_status = GetVariable(L"DUMMY_DEBUG", &data, &dataSize, guid); + if (EFI_ERROR(efi_status)) { + return; + } + + Print(L"add-symbol-file /usr/lib/debug/boot/efi/debughook.debug " + L"0x%08x -s .data 0x%08x\n", &_text, &_data); + + Print(L"Pausing for debugger attachment.\n"); + Print(L"To disable this, remove the EFI variable DUMMY_DEBUG-%g .\n", + &guid); + x = 1; + while (x++) { + /* Make this so it can't /totally/ DoS us. */ +#if defined(__x86_64__) || defined(__i386__) || defined(__i686__) + if (x > 4294967294ULL) + break; + __asm__ __volatile__("pause"); +#elif defined(__aarch64__) + if (x > 1000) + break; + __asm__ __volatile__("wfi"); +#else + if (x > 12000) + break; + uefi_call_wrapper(BS->Stall, 1, 5000); +#endif + } + x = 1; +} + + +EFI_STATUS +efi_main (EFI_HANDLE image, EFI_SYSTEM_TABLE *systab) +{ + InitializeLib(image, systab); + DebugHook(); + return EFI_SUCCESS; +} diff --git a/gnu-efi/apps/drv0.c b/gnu-efi/apps/drv0.c new file mode 100644 index 0000000..1d0c06f --- /dev/null +++ b/gnu-efi/apps/drv0.c @@ -0,0 +1,191 @@ +/* + * Copyright (C) 2013 David Decotigny + * + * Sample EFI shell session, together with drv0_use.efi: + * + * # Loading first instance: + * + * fs0:\> load drv0.efi + * Driver instance loaded successfully. + * load: Image fs0:\drv0.efi loaded at 2FD7C000 - Success + * + * # Testing 1st instance: + * + * fs0:\> drv0_use.efi + * Playing with driver instance 0... + * Hello Sample UEFI Driver! + * Hello was called 1 time(s). + * + * fs0:\> drv0_use.efi + * Playing with driver instance 0... + * Hello Sample UEFI Driver! + * Hello was called 2 time(s). + * + * # Loading another instance: + * + * fs0:\> load drv0.efi + * Driver instance loaded successfully. + * load: Image fs0:\drv0.efi loaded at 2FD6D000 - Success + * + * # Using both instances: + * + * fs0:\> drv0_use.efi + * Playing with driver instance 0... + * Hello Sample UEFI Driver! + * Hello was called 3 time(s). + * Playing with driver instance 1... + * Hello Sample UEFI Driver! + * Hello was called 1 time(s). + * + * fs0:\> drv0_use.efi + * Playing with driver instance 0... + * Hello Sample UEFI Driver! + * Hello was called 4 time(s). + * Playing with driver instance 1... + * Hello Sample UEFI Driver! + * Hello was called 2 time(s). + * + * # Removing 1st instance: + * + * fs0:\> dh + * Handle dump + * 1: Image(DxeCore) + * [...] + * 79: Image(\/drv0.efi) ImageDevPath (..A,0x800,0x17F7DF)/\/drv0.efi) + * 7A: Image(\/drv0.efi) ImageDevPath (..A,0x800,0x17F7DF)/\/drv0.efi) + * + * fs0:\> unload 79 + * 79: Image(\/drv0.efi) ImageDevPath (..A,0x800,0x17F7DF)/\/drv0.efi) + * Unload driver image (y/n)? y + * Driver instance unloaded. + * unload: Success + * + * # Only 2nd instance remaining: + * + * fs0:\> drv0_use.efi + * Playing with driver instance 0... + * Hello Sample UEFI Driver! + * Hello was called 3 time(s). + * + * # Removing 2nd/last instance: + * + * fs0:\> dh + * Handle dump + * 1: Image(DxeCore) + * [...] + * 79: Image(\/drv0.efi) ImageDevPath (..A,0x800,0x17F7DF)/\/drv0.efi) + * + * fs0:\> unload 79 + * 79: Image(\/drv0.efi) ImageDevPath (..A,0x800,0x17F7DF)/\/drv0.efi) + * Unload driver image (y/n)? y + * Driver instance unloaded. + * unload: Success + * + * # Expect error: no other drv0 instance left + * + * fs0:\> drv0_use.efi + * Error looking up handles for proto: 14 + */ + +#include +#include +#include "drv0.h" + + +static const EFI_GUID GnuEfiAppsDrv0ProtocolGuid + = GNU_EFI_APPS_DRV0_PROTOCOL_GUID; + +static struct { + GNU_EFI_APPS_DRV0_PROTOCOL Proto; + UINTN Counter; +} InternalGnuEfiAppsDrv0ProtocolData; + + +static +EFI_STATUS +EFI_FUNCTION +Drv0SayHello( + IN const CHAR16 *HelloWho + ) +{ + if (! HelloWho) + return EFI_INVALID_PARAMETER; + + Print(L"Hello %s!\n", HelloWho); + InternalGnuEfiAppsDrv0ProtocolData.Counter ++; + return EFI_SUCCESS; +} + + +static +EFI_STATUS +EFI_FUNCTION +Drv0GetNumberOfHello( + OUT UINTN *NumberOfHello + ) +{ + if (! NumberOfHello) + return EFI_INVALID_PARAMETER; + + *NumberOfHello = InternalGnuEfiAppsDrv0ProtocolData.Counter; + return EFI_SUCCESS; +} + + +static +EFI_STATUS +EFI_FUNCTION +Drv0Unload(IN EFI_HANDLE ImageHandle) +{ + LibUninstallProtocolInterfaces(ImageHandle, + &GnuEfiAppsDrv0ProtocolGuid, + &InternalGnuEfiAppsDrv0ProtocolData.Proto, + NULL); + Print(L"Driver instance unloaded.\n", ImageHandle); + return EFI_SUCCESS; +} + + +EFI_STATUS +efi_main (EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SysTab) +{ + EFI_STATUS Status; + EFI_LOADED_IMAGE *LoadedImage = NULL; + + InitializeLib(ImageHandle, SysTab); + + /* Initialize global protocol definition + data */ + InternalGnuEfiAppsDrv0ProtocolData.Proto.SayHello + = (GNU_EFI_APPS_DRV0_SAY_HELLO) Drv0SayHello; + InternalGnuEfiAppsDrv0ProtocolData.Proto.GetNumberOfHello + = (GNU_EFI_APPS_DRV0_GET_NUMBER_OF_HELLO) Drv0GetNumberOfHello; + InternalGnuEfiAppsDrv0ProtocolData.Counter = 0; + + /* Grab handle to this image: we'll attach our proto instance to it */ + Status = uefi_call_wrapper(BS->OpenProtocol, 6, + ImageHandle, &LoadedImageProtocol, + (void**)&LoadedImage, ImageHandle, + NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL); + if (EFI_ERROR(Status)) { + Print(L"Could not open loaded image protocol: %d\n", Status); + return Status; + } + + /* Attach our proto to the current driver image */ + Status = LibInstallProtocolInterfaces( + &ImageHandle, &GnuEfiAppsDrv0ProtocolGuid, + &InternalGnuEfiAppsDrv0ProtocolData.Proto, NULL); + if (EFI_ERROR(Status)) { + Print(L"Error registering driver instance: %d\n", Status); + return Status; + } + + /* Register Unload callback, used to unregister current protocol + * instance from system */ + LoadedImage->Unload = (EFI_IMAGE_UNLOAD)Drv0Unload; + + Print(L"Driver instance loaded successfully.\n"); + return EFI_SUCCESS; /* at this point, this instance stays resident + * until image is unloaded, eg. with shell's unload, + * ExitBootServices() */ +} diff --git a/gnu-efi/apps/drv0.h b/gnu-efi/apps/drv0.h new file mode 100644 index 0000000..cf0e054 --- /dev/null +++ b/gnu-efi/apps/drv0.h @@ -0,0 +1,35 @@ +#ifndef _GNU_EFI_APPS_DRV0_H_ +#define _GNU_EFI_APPS_DRV0_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/* UEFI naming conventions */ +#define GNU_EFI_APPS_DRV0_PROTOCOL_GUID \ +{ 0xe4dcafd0, 0x586c, 0x4b3d, {0x86, 0xe7, 0x28, 0xde, 0x7f, 0xcc, 0x04, 0xb9} } + +INTERFACE_DECL(_GNU_EFI_APPS_DRV0_PROTOCOL); + +typedef +EFI_STATUS +(EFIAPI *GNU_EFI_APPS_DRV0_SAY_HELLO) ( + IN const CHAR16 *HelloWho + ); + +typedef +EFI_STATUS +(EFIAPI *GNU_EFI_APPS_DRV0_GET_NUMBER_OF_HELLO) ( + OUT UINTN *NumberOfHello + ); + +typedef struct _GNU_EFI_APPS_DRV0_PROTOCOL { + GNU_EFI_APPS_DRV0_SAY_HELLO SayHello; + GNU_EFI_APPS_DRV0_GET_NUMBER_OF_HELLO GetNumberOfHello; +} GNU_EFI_APPS_DRV0_PROTOCOL; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/gnu-efi/apps/drv0_use.c b/gnu-efi/apps/drv0_use.c new file mode 100644 index 0000000..d8688cf --- /dev/null +++ b/gnu-efi/apps/drv0_use.c @@ -0,0 +1,79 @@ +/* + * Copyright (C) 2013 David Decotigny + * + * See drv0.c for an example session. + */ + +#include +#include +#include "drv0.h" + + +static EFI_GUID GnuEfiAppsDrv0ProtocolGuid + = GNU_EFI_APPS_DRV0_PROTOCOL_GUID; + + +static +EFI_STATUS +PlayWithGnuEfiAppsDrv0Protocol(IN EFI_HANDLE DrvHandle) { + EFI_STATUS Status; + GNU_EFI_APPS_DRV0_PROTOCOL *drv = NULL; + UINTN NumberOfHello = 0; + + Status = uefi_call_wrapper(BS->OpenProtocol, 6, + DrvHandle, + &GnuEfiAppsDrv0ProtocolGuid, + (void**)&drv, + DrvHandle, + NULL, + EFI_OPEN_PROTOCOL_GET_PROTOCOL); + if (EFI_ERROR(Status)) { + Print(L"Cannot open proto: %d\n", Status); + return Status; + } + + Status = uefi_call_wrapper(drv->SayHello, 2, L"Sample UEFI Driver"); + if (EFI_ERROR(Status)) { + Print(L"Cannot call SayHello: %d\n", Status); + } + + Status = uefi_call_wrapper(drv->GetNumberOfHello, 2, &NumberOfHello); + if (EFI_ERROR(Status)) { + Print(L"Cannot call GetNumberOfHello: %d\n", Status); + } else { + Print(L"Hello was called %d time(s).\n", NumberOfHello); + } + + return EFI_SUCCESS; +} + + +EFI_STATUS +efi_main (EFI_HANDLE Image, EFI_SYSTEM_TABLE *SysTab) +{ + EFI_STATUS Status; + EFI_HANDLE *Handles = NULL; + UINTN i, NoHandles = 0; + + InitializeLib(Image, SysTab); + + Status = LibLocateHandle(ByProtocol, &GnuEfiAppsDrv0ProtocolGuid, + NULL, &NoHandles, &Handles); + if (EFI_ERROR(Status)) { + Print(L"Error looking up handles for proto: %d\n", Status); + return Status; + } + + for (i = 0 ; i < NoHandles ; ++i) + { + Print(L"Playing with driver instance %d...\n", i); + Status = PlayWithGnuEfiAppsDrv0Protocol(Handles[i]); + if (EFI_ERROR(Status)) + Print(L"Error playing with instance %d, skipping\n", i); + } + + if (Handles) + FreePool(Handles); + + return EFI_SUCCESS; +} diff --git a/gnu-efi/apps/exit.c b/gnu-efi/apps/exit.c new file mode 100644 index 0000000..78b94a5 --- /dev/null +++ b/gnu-efi/apps/exit.c @@ -0,0 +1,12 @@ +#include +#include + +EFI_STATUS +efi_main (EFI_HANDLE image_handle, EFI_SYSTEM_TABLE *systab) +{ + InitializeLib(image_handle, systab); + + Exit(EFI_SUCCESS, 0, NULL); + + return EFI_UNSUPPORTED; +} diff --git a/gnu-efi/apps/lfbgrid.c b/gnu-efi/apps/lfbgrid.c new file mode 100644 index 0000000..53a255a --- /dev/null +++ b/gnu-efi/apps/lfbgrid.c @@ -0,0 +1,170 @@ +#include +#include + +extern EFI_GUID GraphicsOutputProtocol; + +#define be32_to_cpu(x) __builtin_bswap32(x) + +static void +fill_boxes(UINT32 *PixelBuffer, UINT32 Width, UINT32 Height, UINT32 Pitch, + EFI_GRAPHICS_PIXEL_FORMAT Format, EFI_PIXEL_BITMASK Info ) +{ + UINT32 Red, Green; + UINT32 y, x, color; + + switch(Format) { + case PixelRedGreenBlueReserved8BitPerColor: + Red = be32_to_cpu(0xff000000); + Green = be32_to_cpu(0x00ff0000); + break; + case PixelBlueGreenRedReserved8BitPerColor: + Red = be32_to_cpu(0x0000ff00); + Green = be32_to_cpu(0x00ff0000); + break; + case PixelBitMask: + Red = Info.RedMask; + Green = Info.GreenMask; + break; + case PixelBltOnly: + return; + default: + Print(L"Invalid pixel format\n"); + return; + } + + for (y = 0; y < Height; y++) { + color = ((y / 32) % 2 == 0) ? Red : Green; + for (x = 0; x < Width; x++) { + if (x % 32 == 0 && x != 0) + color = (color == Red) ? Green : Red; + PixelBuffer[y * Pitch + x] = color; + } + } +} + +static void +draw_boxes(EFI_GRAPHICS_OUTPUT_PROTOCOL *gop) +{ + int i, imax; + EFI_STATUS rc; + EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *info; + UINTN NumPixels; + UINT32 *PixelBuffer; + UINT32 CopySize, BufferSize; +#if defined(__x86_64__) || defined(__aarch64__) + UINT64 FrameBufferAddr; +#elif defined(__i386__) || defined(__arm__) + UINT32 FrameBufferAddr; +#else +#error YOUR ARCH HERE +#endif + + if (gop->Mode) { + imax = gop->Mode->MaxMode; + } else { + Print(L"gop->Mode is NULL\n"); + return; + } + + for (i = 0; i < imax; i++) { + UINTN SizeOfInfo; + rc = uefi_call_wrapper(gop->QueryMode, 4, gop, i, &SizeOfInfo, + &info); + if (EFI_ERROR(rc) && rc == EFI_NOT_STARTED) { + Print(L"gop->QueryMode() returned %r\n", rc); + Print(L"Trying to start GOP with SetMode().\n"); + rc = uefi_call_wrapper(gop->SetMode, 2, gop, + gop->Mode ? gop->Mode->Mode : 0); + rc = uefi_call_wrapper(gop->QueryMode, 4, gop, i, + &SizeOfInfo, &info); + } + + if (EFI_ERROR(rc)) { + Print(L"%d: Bad response from QueryMode: %r (%d)\n", + i, rc, rc); + continue; + } + + if (CompareMem(info, gop->Mode->Info, sizeof (*info))) + continue; + + NumPixels = info->VerticalResolution * info->PixelsPerScanLine; + BufferSize = NumPixels * sizeof(UINT32); + if (BufferSize == gop->Mode->FrameBufferSize) { + CopySize = BufferSize; + } else { + CopySize = BufferSize < gop->Mode->FrameBufferSize ? + BufferSize : gop->Mode->FrameBufferSize; + Print(L"height * pitch * pixelsize = %lu buf fb size is %lu; using %lu\n", + BufferSize, gop->Mode->FrameBufferSize, CopySize); + } + + PixelBuffer = AllocatePool(BufferSize); + if (!PixelBuffer) { + Print(L"Allocation of 0x%08lx bytes failed.\n", + sizeof(UINT32) * NumPixels); + return; + } + + fill_boxes(PixelBuffer, info->HorizontalResolution, + info->VerticalResolution, info->PixelsPerScanLine, + info->PixelFormat, info->PixelInformation); + + if (info->PixelFormat == PixelBltOnly) { + Print(L"No linear framebuffer on this device.\n"); + return; + } +#if defined(__x86_64__) || defined(__aarch64__) + FrameBufferAddr = (UINT64)gop->Mode->FrameBufferBase; +#elif defined(__i386__) || defined(__arm__) + FrameBufferAddr = (UINT32)(UINT64)gop->Mode->FrameBufferBase; +#else +#error YOUR ARCH HERE +#endif + + CopyMem((VOID *)FrameBufferAddr, PixelBuffer, CopySize); + return; + } + Print(L"Never found the active video mode?\n"); +} + +static EFI_STATUS +SetWatchdog(UINTN seconds) +{ + EFI_STATUS rc; + rc = uefi_call_wrapper(BS->SetWatchdogTimer, 4, seconds, 0x1ffff, + 0, NULL); + if (EFI_ERROR(rc)) { + CHAR16 Buffer[64]; + StatusToString(Buffer, rc); + Print(L"Bad response from QueryMode: %s (%d)\n", Buffer, rc); + } + return rc; +} + +EFI_STATUS +efi_main (EFI_HANDLE image_handle, EFI_SYSTEM_TABLE *systab) +{ + EFI_STATUS rc; + EFI_GRAPHICS_OUTPUT_PROTOCOL *gop; + + InitializeLib(image_handle, systab); + + SetWatchdog(10); + + rc = LibLocateProtocol(&GraphicsOutputProtocol, (void **)&gop); + if (EFI_ERROR(rc)) { + Print(L"Could not locate GOP: %r\n", rc); + return rc; + } + + if (!gop) { + Print(L"LocateProtocol(GOP, &gop) returned %r but GOP is NULL\n", rc); + return EFI_UNSUPPORTED; + } + + draw_boxes(gop); + + SetWatchdog(0); + return EFI_SUCCESS; +} diff --git a/gnu-efi/apps/modelist.c b/gnu-efi/apps/modelist.c new file mode 100644 index 0000000..26892e1 --- /dev/null +++ b/gnu-efi/apps/modelist.c @@ -0,0 +1,108 @@ +#include +#include + +extern EFI_GUID GraphicsOutputProtocol; + +static void +print_modes(EFI_GRAPHICS_OUTPUT_PROTOCOL *gop) +{ + int i, imax; + EFI_STATUS rc; + + if (gop->Mode) { + imax = gop->Mode->MaxMode; + Print(L"GOP reports MaxMode %d\n", imax); + } else { + Print(L"gop->Mode is NULL\n"); + imax = 1; + } + + for (i = 0; i < imax; i++) { + EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *info; + UINTN SizeOfInfo; + rc = uefi_call_wrapper(gop->QueryMode, 4, gop, i, &SizeOfInfo, + &info); + if (EFI_ERROR(rc) && rc == EFI_NOT_STARTED) { + Print(L"gop->QueryMode() returned %r\n", rc); + Print(L"Trying to start GOP with SetMode().\n"); + rc = uefi_call_wrapper(gop->SetMode, 2, gop, + gop->Mode ? gop->Mode->Mode : 0); + rc = uefi_call_wrapper(gop->QueryMode, 4, gop, i, + &SizeOfInfo, &info); + } + + if (EFI_ERROR(rc)) { + Print(L"%d: Bad response from QueryMode: %r (%d)\n", + i, rc, rc); + continue; + } + Print(L"%c%d: %dx%d ", + (gop->Mode && + CompareMem(info,gop->Mode->Info,sizeof(*info)) == 0 + ) ? '*' : ' ', + i, info->HorizontalResolution, info->VerticalResolution); + switch(info->PixelFormat) { + case PixelRedGreenBlueReserved8BitPerColor: + Print(L"RGBR"); + break; + case PixelBlueGreenRedReserved8BitPerColor: + Print(L"BGRR"); + break; + case PixelBitMask: + Print(L"R:%08x G:%08x B:%08x X:%08x", + info->PixelInformation.RedMask, + info->PixelInformation.GreenMask, + info->PixelInformation.BlueMask, + info->PixelInformation.ReservedMask); + break; + case PixelBltOnly: + Print(L"(blt only)"); + break; + default: + Print(L"(Invalid pixel format)"); + break; + } + Print(L" pitch %d\n", info->PixelsPerScanLine); + } +} + +static EFI_STATUS +SetWatchdog(UINTN seconds) +{ + EFI_STATUS rc; + rc = uefi_call_wrapper(BS->SetWatchdogTimer, 4, seconds, 0x1ffff, + 0, NULL); + if (EFI_ERROR(rc)) { + CHAR16 Buffer[64]; + StatusToString(Buffer, rc); + Print(L"Bad response from QueryMode: %s (%d)\n", Buffer, rc); + } + return rc; +} + +EFI_STATUS +efi_main (EFI_HANDLE image_handle, EFI_SYSTEM_TABLE *systab) +{ + EFI_STATUS rc; + EFI_GRAPHICS_OUTPUT_PROTOCOL *gop; + + InitializeLib(image_handle, systab); + + SetWatchdog(10); + + rc = LibLocateProtocol(&GraphicsOutputProtocol, (void **)&gop); + if (EFI_ERROR(rc)) { + Print(L"Could not locate GOP: %r\n", rc); + return rc; + } + + if (!gop) { + Print(L"LocateProtocol(GOP, &gop) returned %r but GOP is NULL\n", rc); + return EFI_UNSUPPORTED; + } + + print_modes(gop); + + SetWatchdog(0); + return EFI_SUCCESS; +} diff --git a/gnu-efi/apps/printenv.c b/gnu-efi/apps/printenv.c new file mode 100644 index 0000000..6341e40 --- /dev/null +++ b/gnu-efi/apps/printenv.c @@ -0,0 +1,32 @@ +#include +#include + +EFI_STATUS +efi_main (EFI_HANDLE image, EFI_SYSTEM_TABLE *systab) +{ + EFI_STATUS status; + CHAR16 name[256], *val, fmt[20]; + EFI_GUID vendor; + UINTN size; + + InitializeLib(image, systab); + + name[0] = 0; + vendor = NullGuid; + + Print(L"GUID Variable Name Value\n"); + Print(L"=================================== ==================== ========\n"); + + StrCpy(fmt, L"%.-35g %.-20s %s\n"); + while (1) { + size = sizeof(name); + status = uefi_call_wrapper(RT->GetNextVariableName, 3, &size, name, &vendor); + if (status != EFI_SUCCESS) + break; + + val = LibGetVariable(name, &vendor); + Print(fmt, &vendor, name, val); + FreePool(val); + } + return EFI_SUCCESS; +} diff --git a/gnu-efi/apps/route80h.c b/gnu-efi/apps/route80h.c new file mode 100644 index 0000000..5272dd3 --- /dev/null +++ b/gnu-efi/apps/route80h.c @@ -0,0 +1,136 @@ +#include +#include + +/* this example program changes the Reserved Page Route (RPR) bit on ICH10's General + * Control And Status Register (GCS) from LPC to PCI. In practical terms, it routes + * outb to port 80h to the PCI bus. */ + +#define GCS_OFFSET_ADDR 0x3410 +#define GCS_RPR_SHIFT 2 +#define GCS_RPR_PCI 1 +#define GCS_RPR_LPC 0 + +#define VENDOR_ID_INTEL 0x8086 +#define DEVICE_ID_LPCIF 0x3a16 +#define DEVICE_ID_COUGARPOINT_LPCIF 0x1c56 + +static EFI_HANDLE ImageHandle; + +typedef struct { + uint16_t vendor_id; /* 00-01 */ + uint16_t device_id; /* 02-03 */ + char pad[0xEB]; /* 04-EF */ + uint32_t rcba; /* F0-F3 */ + uint32_t reserved[3]; /* F4-FF */ +} lpcif_t; + +static inline void set_bit(volatile uint32_t *flag, int bit, int value) +{ + uint32_t val = *flag; + Print(L"current value is 0x%2x\n", val); + + if (value) { + val |= (1 << bit); + } else { + val &= ~(1 << bit); + } + Print(L"setting value to 0x%2x\n", val); + *flag = val; + val = *flag; + Print(L"new value is 0x%2x\n", val); +} + +static int is_device(EFI_PCI_IO *pciio, uint16_t vendor_id, uint16_t device_id) +{ + lpcif_t lpcif; + EFI_STATUS rc; + + rc = uefi_call_wrapper(pciio->Pci.Read, 5, pciio, EfiPciIoWidthUint16, 0, 2, &lpcif); + if (EFI_ERROR(rc)) + return 0; + + if (vendor_id == lpcif.vendor_id && device_id == lpcif.device_id) + return 1; + return 0; +} + +static EFI_STATUS find_pci_device(uint16_t vendor_id, uint16_t device_id, + EFI_PCI_IO **pciio) +{ + EFI_STATUS rc; + EFI_HANDLE *Handles; + UINTN NoHandles, i; + + if (!pciio) + return EFI_INVALID_PARAMETER; + + rc = LibLocateHandle(ByProtocol, &PciIoProtocol, NULL, &NoHandles, + &Handles); + if (EFI_ERROR(rc)) + return rc; + + for (i = 0; i < NoHandles; i++) { + void *pciio_tmp = NULL; + rc = uefi_call_wrapper(BS->OpenProtocol, 6, Handles[i], + &PciIoProtocol, &pciio_tmp, ImageHandle, + NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL); + if (EFI_ERROR(rc)) + continue; + *pciio = pciio_tmp; + if (!is_device(*pciio, vendor_id, device_id)) { + *pciio = NULL; + continue; + } + + return EFI_SUCCESS; + } + return EFI_NOT_FOUND; +} + +EFI_STATUS +efi_main (EFI_HANDLE image_handle, EFI_SYSTEM_TABLE *systab) +{ + InitializeLib(image_handle, systab); + EFI_PCI_IO *pciio = NULL; + lpcif_t lpcif; + EFI_STATUS rc = EFI_SUCCESS; + struct { + uint16_t vendor; + uint16_t device; + } devices[] = { + { VENDOR_ID_INTEL, DEVICE_ID_LPCIF }, + { VENDOR_ID_INTEL, DEVICE_ID_COUGARPOINT_LPCIF }, + { 0, 0 } + }; + int i; + + ImageHandle = image_handle; + for (i = 0; devices[i].vendor != 0; i++) { + rc = find_pci_device(devices[i].vendor, devices[i].device, &pciio); + if (EFI_ERROR(rc)) + continue; + } + + if (rc == EFI_NOT_FOUND) { + Print(L"Device not found.\n"); + return rc; + } else if (EFI_ERROR(rc)) { + return rc; + } + + rc = uefi_call_wrapper(pciio->Pci.Read, 5, pciio, EfiPciIoWidthUint32, + EFI_FIELD_OFFSET(lpcif_t, rcba), 1, &lpcif.rcba); + if (EFI_ERROR(rc)) + return rc; + if (!(lpcif.rcba & 1)) { + Print(L"rcrb is not mapped, cannot route port 80h\n"); + return EFI_UNSUPPORTED; + } + lpcif.rcba &= ~1UL; + + Print(L"rcba: 0x%8x\n", lpcif.rcba, lpcif.rcba); + set_bit((uint32_t *)(intptr_t)(lpcif.rcba + GCS_OFFSET_ADDR), + GCS_RPR_SHIFT, GCS_RPR_PCI); + + return EFI_SUCCESS; +} diff --git a/gnu-efi/apps/setdbg.c b/gnu-efi/apps/setdbg.c new file mode 100644 index 0000000..897140e --- /dev/null +++ b/gnu-efi/apps/setdbg.c @@ -0,0 +1,37 @@ +#include +#include + +EFI_GUID GRUB_EFI_GRUB_VARIABLE_GUID = {0x91376aff,0xcba6,0x42be,{0x94,0x9d,0x06,0xfd,0xe8,0x11,0x28,0xe8}}; +EFI_GUID SHIM_GUID = {0x605dab50,0xe046,0x4300,{0xab,0xb6,0x3d,0xd8,0x10,0xdd,0x8b,0x23}}; + +char grubenv[] = "# GRUB Environment Block\n\ +debug=tcp,http,net\n\ +####################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################"; + +EFI_STATUS +efi_main (EFI_HANDLE image, EFI_SYSTEM_TABLE *systab) +{ + EFI_STATUS status; + InitializeLib(image, systab); +#if 0 + UINT8 data = 1; + + status = RT->SetVariable(L"SHIM_DEBUG", &SHIM_GUID, + EFI_VARIABLE_NON_VOLATILE | + EFI_VARIABLE_BOOTSERVICE_ACCESS | + EFI_VARIABLE_RUNTIME_ACCESS, + sizeof(data), &data); + if (EFI_ERROR(status)) + Print(L"SetVariable failed: %r\n", status); +#endif + + status = RT->SetVariable(L"GRUB_ENV", &SHIM_GUID, + EFI_VARIABLE_NON_VOLATILE | + EFI_VARIABLE_BOOTSERVICE_ACCESS | + EFI_VARIABLE_RUNTIME_ACCESS, + sizeof(grubenv)-1, grubenv); + if (EFI_ERROR(status)) + Print(L"SetVariable(GRUB_ENV) failed: %r\n", status); + + return EFI_SUCCESS; +} diff --git a/gnu-efi/apps/setjmp.c b/gnu-efi/apps/setjmp.c new file mode 100644 index 0000000..d9e0f29 --- /dev/null +++ b/gnu-efi/apps/setjmp.c @@ -0,0 +1,32 @@ + +#include +#include +#include + +EFI_STATUS +efi_main( + EFI_HANDLE image_handle, + EFI_SYSTEM_TABLE *systab +) +{ + jmp_buf env; + int rc; + + InitializeLib(image_handle, systab); + rc = setjmp(env); + Print(L"setjmp() = %d\n", rc); + + if (rc == 3) { + Print(L"3 worked\n"); + longjmp(env, 0); + return 0; + } + + if (rc == 1) { + Print(L"0 got to be one yay\n"); + return 0; + } + + longjmp(env, 3); + return 0; +} diff --git a/gnu-efi/apps/t.c b/gnu-efi/apps/t.c new file mode 100644 index 0000000..c7e3d57 --- /dev/null +++ b/gnu-efi/apps/t.c @@ -0,0 +1,27 @@ +#include +#include + +static CHAR16 * +a2u (char *str) +{ + static CHAR16 mem[2048]; + int i; + + for (i = 0; str[i]; ++i) + mem[i] = (CHAR16) str[i]; + mem[i] = 0; + return mem; +} + +EFI_STATUS +efi_main (EFI_HANDLE image_handle, EFI_SYSTEM_TABLE *systab) +{ + SIMPLE_TEXT_OUTPUT_INTERFACE *conout; + + InitializeLib(image_handle, systab); + conout = systab->ConOut; + uefi_call_wrapper(conout->OutputString, 2, conout, (CHAR16 *)L"Hello World!\n\r"); + uefi_call_wrapper(conout->OutputString, 2, conout, a2u("Hello World!\n\r")); + + return EFI_SUCCESS; +} diff --git a/gnu-efi/apps/t2.c b/gnu-efi/apps/t2.c new file mode 100644 index 0000000..6a09c42 --- /dev/null +++ b/gnu-efi/apps/t2.c @@ -0,0 +1,14 @@ +#include +#include + +EFI_STATUS +efi_main (EFI_HANDLE image, EFI_SYSTEM_TABLE *systab) +{ + SIMPLE_TEXT_OUTPUT_INTERFACE *conout; + + InitializeLib(image, systab); + conout = systab->ConOut; + uefi_call_wrapper(conout->OutputString, 2, conout, L"Hello World!\n\r"); + + return EFI_SUCCESS; +} diff --git a/gnu-efi/apps/t3.c b/gnu-efi/apps/t3.c new file mode 100644 index 0000000..623830a --- /dev/null +++ b/gnu-efi/apps/t3.c @@ -0,0 +1,95 @@ +#include +#include + +EFI_STATUS +efi_main( + EFI_HANDLE image_handle, + EFI_SYSTEM_TABLE *systab +) +{ + EFI_GUID loaded_image_protocol = LOADED_IMAGE_PROTOCOL; + EFI_STATUS efi_status; + EFI_LOADED_IMAGE *li; + UINTN pat = PoolAllocationType; + VOID *void_li_p; + + InitializeLib(image_handle, systab); + PoolAllocationType = 2; /* klooj */ + + Print(L"Hello World! (0xd=0x%x, 13=%d)\n", 13, 13); + + Print(L"before InitializeLib(): PoolAllocationType=%d\n", + pat); + + Print(L" after InitializeLib(): PoolAllocationType=%d\n", + PoolAllocationType); + + /* + * Locate loaded_image_handle instance. + */ + + Print(L"BS->HandleProtocol() "); + + efi_status = uefi_call_wrapper( + BS->HandleProtocol, + 3, + image_handle, + &loaded_image_protocol, + &void_li_p); + li = void_li_p; + + Print(L"%xh (%r)\n", efi_status, efi_status); + + if (efi_status != EFI_SUCCESS) { + return efi_status; + } + + Print(L" li: %xh\n", li); + + if (!li) { + return EFI_UNSUPPORTED; + } + + Print(L" li->Revision: %xh\n", li->Revision); + Print(L" li->ParentHandle: %xh\n", li->ParentHandle); + Print(L" li->SystemTable: %xh\n", li->SystemTable); + Print(L" li->DeviceHandle: %xh\n", li->DeviceHandle); + Print(L" li->FilePath: %xh\n", li->FilePath); + Print(L" li->Reserved: %xh\n", li->Reserved); + Print(L" li->LoadOptionsSize: %xh\n", li->LoadOptionsSize); + Print(L" li->LoadOptions: %xh\n", li->LoadOptions); + Print(L" li->ImageBase: %xh\n", li->ImageBase); + Print(L" li->ImageSize: %xh\n", li->ImageSize); + Print(L" li->ImageCodeType: %xh\n", li->ImageCodeType); + Print(L" li->ImageDataType: %xh\n", li->ImageDataType); + Print(L" li->Unload: %xh\n", li->Unload); + +#if 0 +typedef struct { + UINT32 Revision; + EFI_HANDLE ParentHandle; + struct _EFI_SYSTEM_TABLE *SystemTable; + + // Source location of image + EFI_HANDLE DeviceHandle; + EFI_DEVICE_PATH *FilePath; + VOID *Reserved; + + // Images load options + UINT32 LoadOptionsSize; + VOID *LoadOptions; + + // Location of where image was loaded + VOID *ImageBase; + UINT64 ImageSize; + EFI_MEMORY_TYPE ImageCodeType; + EFI_MEMORY_TYPE ImageDataType; + + // If the driver image supports a dynamic unload request + EFI_IMAGE_UNLOAD Unload; + +} EFI_LOADED_IMAGE; +#endif + + return EFI_SUCCESS; +} diff --git a/gnu-efi/apps/t4.c b/gnu-efi/apps/t4.c new file mode 100644 index 0000000..b8487ec --- /dev/null +++ b/gnu-efi/apps/t4.c @@ -0,0 +1,14 @@ +#include +#include + +EFI_STATUS +efi_main (EFI_HANDLE *image, EFI_SYSTEM_TABLE *systab) +{ + UINTN index; + + InitializeLib(image, systab); + uefi_call_wrapper(systab->ConOut->OutputString, 2, systab->ConOut, L"Hello application started\r\n"); + uefi_call_wrapper(systab->ConOut->OutputString, 2, systab->ConOut, L"\r\n\r\n\r\nHit any key to exit\r\n"); + uefi_call_wrapper(systab->BootServices->WaitForEvent, 3, 1, &systab->ConIn->WaitForKey, &index); + return EFI_SUCCESS; +} diff --git a/gnu-efi/apps/t5.c b/gnu-efi/apps/t5.c new file mode 100644 index 0000000..7c868d2 --- /dev/null +++ b/gnu-efi/apps/t5.c @@ -0,0 +1,13 @@ +#include +#include + +EFI_STATUS +efi_main (EFI_HANDLE image, EFI_SYSTEM_TABLE *systab) +{ + InitializeLib(image, systab); + Print(L"HelloLib application started\n"); + Print(L"\n\n\nHit any key to exit this image\n"); + WaitForSingleEvent(ST->ConIn->WaitForKey, 0); + uefi_call_wrapper(ST->ConOut->OutputString, 2, ST->ConOut, L"\n\n"); + return EFI_SUCCESS; +} diff --git a/gnu-efi/apps/t6.c b/gnu-efi/apps/t6.c new file mode 100644 index 0000000..f95ea66 --- /dev/null +++ b/gnu-efi/apps/t6.c @@ -0,0 +1,43 @@ +#include +#include + +typedef EFI_STATUS (*foo_t)(EFI_HANDLE, EFI_GUID *, VOID **); +typedef struct { + unsigned long addr; + unsigned long gp; +} fdesc_t; + +EFI_LOADED_IMAGE my_loaded; + +EFI_STATUS +efi_main (EFI_HANDLE image, EFI_SYSTEM_TABLE *systab) +{ + EFI_LOADED_IMAGE *loaded_image = NULL; +#if 0 + EFI_DEVICE_PATH *dev_path; +#endif + EFI_STATUS status; + + InitializeLib(image, systab); + status = uefi_call_wrapper(systab->BootServices->HandleProtocol, + 3, + image, + &LoadedImageProtocol, + (void **) &loaded_image); + if (EFI_ERROR(status)) { + Print(L"handleprotocol: %r\n", status); + } + +#if 0 + BS->HandleProtocol(loaded_image->DeviceHandle, &DevicePathProtocol, (void **) &dev_path); + + Print(L"Image device : %s\n", DevicePathToStr(dev_path)); + Print(L"Image file : %s\n", DevicePathToStr(loaded_image->FilePath)); +#endif + Print(L"Image base : %lx\n", loaded_image->ImageBase); + Print(L"Image size : %lx\n", loaded_image->ImageSize); + Print(L"Load options size : %lx\n", loaded_image->LoadOptionsSize); + Print(L"Load options : %s\n", loaded_image->LoadOptions); + + return EFI_SUCCESS; +} diff --git a/gnu-efi/apps/t7.c b/gnu-efi/apps/t7.c new file mode 100644 index 0000000..f02aaee --- /dev/null +++ b/gnu-efi/apps/t7.c @@ -0,0 +1,25 @@ +#include +#include + +EFI_STATUS +efi_main (EFI_HANDLE image, EFI_SYSTEM_TABLE *systab) +{ + EFI_INPUT_KEY efi_input_key; + EFI_STATUS efi_status; + + InitializeLib(image, systab); + + Print(L"HelloLib application started\n"); + + Print(L"\n\n\nHit any key to exit this image\n"); + WaitForSingleEvent(ST->ConIn->WaitForKey, 0); + + uefi_call_wrapper(ST->ConOut->OutputString, 2, ST->ConOut, L"\n\n"); + + efi_status = uefi_call_wrapper(ST->ConIn->ReadKeyStroke, 2, ST->ConIn, &efi_input_key); + + Print(L"ScanCode: %xh UnicodeChar: %xh CallRtStatus: %x\n", + efi_input_key.ScanCode, efi_input_key.UnicodeChar, efi_status); + + return EFI_SUCCESS; +} diff --git a/gnu-efi/apps/t8.c b/gnu-efi/apps/t8.c new file mode 100644 index 0000000..10f8811 --- /dev/null +++ b/gnu-efi/apps/t8.c @@ -0,0 +1,19 @@ +#include +#include + +EFI_STATUS +efi_main (EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable) +{ + INTN Argc, i; + CHAR16 **Argv; + + InitializeLib(ImageHandle, SystemTable); + Argc = GetShellArgcArgv(ImageHandle, &Argv); + + Print(L"Hello World, started with Argc=%d\n", Argc); + for (i = 0 ; i < Argc ; ++i) + Print(L" Argv[%d] = '%s'\n", i, Argv[i]); + + Print(L"Bye.\n"); + return EFI_SUCCESS; +} diff --git a/gnu-efi/apps/tcc.c b/gnu-efi/apps/tcc.c new file mode 100644 index 0000000..09ad98b --- /dev/null +++ b/gnu-efi/apps/tcc.c @@ -0,0 +1,431 @@ +/* + * Test if our calling convention gymnastics actually work + */ + +#include +#include + +#if 0 +extern void dump_stack(void); +asm( ".globl dump_stack\n" + "dump_stack:\n" + " movq %rsp, %rdi\n" + " jmp *dump_stack_helper@GOTPCREL(%rip)\n" + ".size dump_stack, .-dump_stack"); + +void dump_stack_helper(uint64_t rsp_val) +{ + uint64_t *rsp = (uint64_t *)rsp_val; + int x; + + Print(L"%%rsp: 0x%08x%08x stack:\r\n", + (rsp_val & 0xffffffff00000000) >>32, + rsp_val & 0xffffffff); + for (x = 0; x < 8; x++) { + Print(L"%08x: ", ((uint64_t)rsp) & 0xffffffff); + Print(L"%016x ", *rsp++); + Print(L"%016x ", *rsp++); + Print(L"%016x ", *rsp++); + Print(L"%016x\r\n", *rsp++); + } +} +#endif + +EFI_STATUS EFI_FUNCTION test_failure_callback(void) +{ + return EFI_UNSUPPORTED; +} + +EFI_STATUS test_failure(void) +{ + return uefi_call_wrapper(test_failure_callback, 0); +} + +EFI_STATUS EFI_FUNCTION test_call0_callback(void) +{ + return EFI_SUCCESS; +} + +EFI_STATUS test_call0(void) +{ + return uefi_call_wrapper(test_call0_callback, 0); +} + +EFI_STATUS EFI_FUNCTION test_call1_callback(UINT32 a) +{ + if (a != 0x12345678) { + return EFI_LOAD_ERROR; + } + return EFI_SUCCESS; +} + +EFI_STATUS test_call1(void) +{ + return uefi_call_wrapper(test_call1_callback, 1,0x12345678); +} + +EFI_STATUS EFI_FUNCTION test_call2_callback(UINT32 a, UINT32 b) +{ + if (a != 0x12345678) { + return EFI_LOAD_ERROR; + } + if (b != 0x23456789) { + return EFI_INVALID_PARAMETER; + } + return EFI_SUCCESS; +} + +EFI_STATUS test_call2(void) +{ + return uefi_call_wrapper(test_call2_callback, 2, + 0x12345678, 0x23456789); +} + +EFI_STATUS EFI_FUNCTION test_call3_callback(UINT32 a, UINT32 b, + UINT32 c) +{ + if (a != 0x12345678) + return EFI_LOAD_ERROR; + if (b != 0x23456789) + return EFI_INVALID_PARAMETER; + if (c != 0x3456789a) + return EFI_UNSUPPORTED; + return EFI_SUCCESS; +} + +EFI_STATUS test_call3(void) +{ + return uefi_call_wrapper(test_call3_callback, 3, + 0x12345678, 0x23456789, 0x3456789a); +} + +EFI_STATUS EFI_FUNCTION test_call4_callback(UINT32 a, UINT32 b, + UINT32 c, UINT32 d) +{ + if (a != 0x12345678) + return EFI_LOAD_ERROR; + if (b != 0x23456789) + return EFI_INVALID_PARAMETER; + if (c != 0x3456789a) + return EFI_UNSUPPORTED; + if (d != 0x456789ab) + return EFI_BAD_BUFFER_SIZE; + + return EFI_SUCCESS; +} + +EFI_STATUS test_call4(void) +{ + return uefi_call_wrapper(test_call4_callback, 4, + 0x12345678, 0x23456789, 0x3456789a, 0x456789ab); +} + +EFI_STATUS EFI_FUNCTION test_call5_callback(UINT32 a, UINT32 b, + UINT32 c, UINT32 d, UINT32 e) +{ + if (a != 0x12345678) + return EFI_LOAD_ERROR; + if (b != 0x23456789) + return EFI_INVALID_PARAMETER; + if (c != 0x3456789a) + return EFI_UNSUPPORTED; + if (d != 0x456789ab) + return EFI_BAD_BUFFER_SIZE; + if (e != 0x56789abc) + return EFI_BUFFER_TOO_SMALL; + + return EFI_SUCCESS; +} + +EFI_STATUS test_call5(void) +{ + return uefi_call_wrapper(test_call5_callback, 5, + 0x12345678, 0x23456789, 0x3456789a, 0x456789ab, 0x56789abc); +} + +EFI_STATUS EFI_FUNCTION test_call6_callback(UINT32 a, UINT32 b, + UINT32 c, UINT32 d, UINT32 e, UINT32 f) +{ + if (a != 0x12345678) + return EFI_LOAD_ERROR; + if (b != 0x23456789) + return EFI_INVALID_PARAMETER; + if (c != 0x3456789a) + return EFI_UNSUPPORTED; + if (d != 0x456789ab) + return EFI_BAD_BUFFER_SIZE; + if (e != 0x56789abc) + return EFI_BUFFER_TOO_SMALL; + if (f != 0x6789abcd) + return EFI_NOT_READY; + + return EFI_SUCCESS; +} + +EFI_STATUS test_call6(void) +{ + return uefi_call_wrapper(test_call6_callback, 6, + 0x12345678, 0x23456789, 0x3456789a, 0x456789ab, 0x56789abc, + 0x6789abcd); +} + +EFI_STATUS EFI_FUNCTION test_call7_callback(UINT32 a, UINT32 b, + UINT32 c, UINT32 d, UINT32 e, UINT32 f, UINT32 g) +{ + if (a != 0x12345678) + return EFI_LOAD_ERROR; + if (b != 0x23456789) + return EFI_INVALID_PARAMETER; + if (c != 0x3456789a) + return EFI_UNSUPPORTED; + if (d != 0x456789ab) + return EFI_BAD_BUFFER_SIZE; + if (e != 0x56789abc) + return EFI_BUFFER_TOO_SMALL; + if (f != 0x6789abcd) + return EFI_NOT_READY; + if (g != 0x789abcde) + return EFI_DEVICE_ERROR; + + return EFI_SUCCESS; +} + +EFI_STATUS test_call7(void) +{ + return uefi_call_wrapper(test_call7_callback, 7, + 0x12345678, 0x23456789, 0x3456789a, 0x456789ab, + 0x56789abc, 0x6789abcd, 0x789abcde); +} + +EFI_STATUS EFI_FUNCTION test_call8_callback(UINT32 a, UINT32 b, + UINT32 c, UINT32 d, UINT32 e, UINT32 f, UINT32 g, UINT32 h) +{ + if (a != 0x12345678) + return EFI_LOAD_ERROR; + if (b != 0x23456789) + return EFI_INVALID_PARAMETER; + if (c != 0x3456789a) + return EFI_UNSUPPORTED; + if (d != 0x456789ab) + return EFI_BAD_BUFFER_SIZE; + if (e != 0x56789abc) + return EFI_BUFFER_TOO_SMALL; + if (f != 0x6789abcd) + return EFI_NOT_READY; + if (g != 0x789abcde) + return EFI_DEVICE_ERROR; + if (h != 0x89abcdef) + return EFI_WRITE_PROTECTED; + + return EFI_SUCCESS; +} + +EFI_STATUS test_call8(void) +{ + return uefi_call_wrapper(test_call8_callback, 8, + 0x12345678, + 0x23456789, + 0x3456789a, + 0x456789ab, + 0x56789abc, + 0x6789abcd, + 0x789abcde, + 0x89abcdef); +} + +EFI_STATUS EFI_FUNCTION test_call9_callback(UINT32 a, UINT32 b, + UINT32 c, UINT32 d, UINT32 e, UINT32 f, UINT32 g, UINT32 h, UINT32 i) +{ + if (a != 0x12345678) + return EFI_LOAD_ERROR; + if (b != 0x23456789) + return EFI_INVALID_PARAMETER; + if (c != 0x3456789a) + return EFI_UNSUPPORTED; + if (d != 0x456789ab) + return EFI_BAD_BUFFER_SIZE; + if (e != 0x56789abc) + return EFI_BUFFER_TOO_SMALL; + if (f != 0x6789abcd) + return EFI_NOT_READY; + if (g != 0x789abcde) + return EFI_DEVICE_ERROR; + if (h != 0x89abcdef) + return EFI_WRITE_PROTECTED; + if (i != 0x9abcdef0) + return EFI_OUT_OF_RESOURCES; + + return EFI_SUCCESS; +} + +EFI_STATUS test_call9(void) +{ + return uefi_call_wrapper(test_call9_callback, 9, + 0x12345678, + 0x23456789, + 0x3456789a, + 0x456789ab, + 0x56789abc, + 0x6789abcd, + 0x789abcde, + 0x89abcdef, + 0x9abcdef0); +} + +extern EFI_STATUS test_call10(void); +EFI_STATUS EFI_FUNCTION test_call10_callback(UINT32 a, UINT32 b, + UINT32 c, UINT32 d, UINT32 e, UINT32 f, UINT32 g, UINT32 h, UINT32 i, + UINT32 j) +{ + if (a != 0x12345678) + return EFI_LOAD_ERROR; + if (b != 0x23456789) + return EFI_INVALID_PARAMETER; + if (c != 0x3456789a) + return EFI_UNSUPPORTED; + if (d != 0x456789ab) + return EFI_BAD_BUFFER_SIZE; + if (e != 0x56789abc) + return EFI_BUFFER_TOO_SMALL; + if (f != 0x6789abcd) + return EFI_NOT_READY; + if (g != 0x789abcde) + return EFI_DEVICE_ERROR; + if (h != 0x89abcdef) + return EFI_WRITE_PROTECTED; + if (i != 0x9abcdef0) + return EFI_OUT_OF_RESOURCES; + if (j != 0xabcdef01) + return EFI_VOLUME_CORRUPTED; + + return EFI_SUCCESS; +} + +EFI_STATUS test_call10(void) +{ + return uefi_call_wrapper(test_call10_callback, 10, + 0x12345678, + 0x23456789, + 0x3456789a, + 0x456789ab, + 0x56789abc, + 0x6789abcd, + 0x789abcde, + 0x89abcdef, + 0x9abcdef0, + 0xabcdef01); +} + +EFI_STATUS +efi_main (EFI_HANDLE *image, EFI_SYSTEM_TABLE *systab) +{ + EFI_STATUS rc = EFI_SUCCESS; + + InitializeLib(image, systab); + PoolAllocationType = 2; /* klooj */ + +#ifdef __x86_64__ + __asm__ volatile("out %0,%1" : : "a" ((uint8_t)0x14), "dN" (0x80)); +#endif + + Print(L"Hello\r\n"); + rc = test_failure(); + if (EFI_ERROR(rc)) { + Print(L"Returning Failure works\n"); + } else { + Print(L"Returning failure doesn't work.\r\n"); + Print(L"%%rax was 0x%016x, should have been 0x%016x\n", + rc, EFI_UNSUPPORTED); + return EFI_INVALID_PARAMETER; + } + + rc = test_call0(); + if (!EFI_ERROR(rc)) { + Print(L"0 args works just fine here.\r\n"); + } else { + Print(L"0 args failed: 0x%016x\n", rc); + return rc; + } + + rc = test_call1(); + if (!EFI_ERROR(rc)) { + Print(L"1 arg works just fine here.\r\n"); + } else { + Print(L"1 arg failed: 0x%016x\n", rc); + return rc; + } + + rc = test_call2(); + if (!EFI_ERROR(rc)) { + Print(L"2 args works just fine here.\r\n"); + } else { + Print(L"2 args failed: 0x%016x\n", rc); + return rc; + } + + rc = test_call3(); + if (!EFI_ERROR(rc)) { + Print(L"3 args works just fine here.\r\n"); + } else { + Print(L"3 args failed: 0x%016x\n", rc); + return rc; + } + + rc = test_call4(); + if (!EFI_ERROR(rc)) { + Print(L"4 args works just fine here.\r\n"); + } else { + Print(L"4 args failed: 0x%016x\n", rc); + return rc; + } + + rc = test_call5(); + if (!EFI_ERROR(rc)) { + Print(L"5 args works just fine here.\r\n"); + } else { + Print(L"5 args failed: 0x%016x\n", rc); + return rc; + } + + rc = test_call6(); + if (!EFI_ERROR(rc)) { + Print(L"6 args works just fine here.\r\n"); + } else { + Print(L"6 args failed: 0x%016x\n", rc); + return rc; + } + + rc = test_call7(); + if (!EFI_ERROR(rc)) { + Print(L"7 args works just fine here.\r\n"); + } else { + Print(L"7 args failed: 0x%016x\n", rc); + return rc; + } + + rc = test_call8(); + if (!EFI_ERROR(rc)) { + Print(L"8 args works just fine here.\r\n"); + } else { + Print(L"8 args failed: 0x%016x\n", rc); + return rc; + } + + rc = test_call9(); + if (!EFI_ERROR(rc)) { + Print(L"9 args works just fine here.\r\n"); + } else { + Print(L"9 args failed: 0x%016x\n", rc); + return rc; + } + + rc = test_call10(); + if (!EFI_ERROR(rc)) { + Print(L"10 args works just fine here.\r\n"); + } else { + Print(L"10 args failed: 0x%016x\n", rc); + return rc; + } + + return rc; +} diff --git a/gnu-efi/apps/tpause.c b/gnu-efi/apps/tpause.c new file mode 100644 index 0000000..51c86df --- /dev/null +++ b/gnu-efi/apps/tpause.c @@ -0,0 +1,9 @@ +#include +#include + +EFI_STATUS +efi_main (EFI_HANDLE image, EFI_SYSTEM_TABLE *systab) +{ + Print(L"Press `q' to quit, any other key to continue:\n"); + +} diff --git a/gnu-efi/apps/trivial.S b/gnu-efi/apps/trivial.S new file mode 100644 index 0000000..40bc68f --- /dev/null +++ b/gnu-efi/apps/trivial.S @@ -0,0 +1,43 @@ + .text + .align 4 + + .globl _start +_start: +#if 0 + pushl %ebp + movl %esp,%ebp + pushl %ebx # save ebx + movl 12(%ebp),%eax # eax <- systab + movl 24(%eax),%ebx # ebx <- systab->FirmwareVendor + pushl %ebx + movl 44(%eax),%ebx # ebx <- systab->ConOut + pushl %ebx + movl 4(%ebx),%eax # eax <- conout->OutputString + call *%eax + movl -4(%ebp),%ebx # restore ebx + leave + ret + +#else + + pushl %ebp + movl %esp,%ebp + pushl %ebx + call 0f +0: popl %eax + addl $hello-0b,%eax + pushl %eax + movl 12(%ebp),%eax # eax <- systab + movl 44(%eax),%ebx # ebx <- systab->ConOut + pushl %ebx + movl 4(%ebx),%eax # eax <- conout->OutputString + call *%eax + movl -4(%ebp),%ebx + leave + ret + + .section .rodata + .align 2 +hello: .byte 'h',0,'e',0,'l',0,'l',0,'o',0,'\n',0,'\r',0,0,0 + +#endif diff --git a/gnu-efi/apps/unsetdbg.c b/gnu-efi/apps/unsetdbg.c new file mode 100644 index 0000000..731e09b --- /dev/null +++ b/gnu-efi/apps/unsetdbg.c @@ -0,0 +1,37 @@ +#include +#include + +EFI_GUID GRUB_EFI_GRUB_VARIABLE_GUID = {0x91376aff,0xcba6,0x42be,{0x94,0x9d,0x06,0xfd,0xe8,0x11,0x28,0xe8}}; +EFI_GUID SHIM_GUID = {0x605dab50,0xe046,0x4300,{0xab,0xb6,0x3d,0xd8,0x10,0xdd,0x8b,0x23}}; + +char grubenv[] = "# GRUB Environment Block\n\ +debug=all\n\ +#############################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################"; + +EFI_STATUS +efi_main (EFI_HANDLE image, EFI_SYSTEM_TABLE *systab) +{ + EFI_STATUS status; + UINT8 data = 1; + InitializeLib(image, systab); + + status = RT->SetVariable(L"SHIM_DEBUG", &SHIM_GUID, + EFI_VARIABLE_NON_VOLATILE | + EFI_VARIABLE_BOOTSERVICE_ACCESS | + EFI_VARIABLE_RUNTIME_ACCESS, + 0, &data); + if (EFI_ERROR(status)) + Print(L"SetVariable failed: %r\n", status); + +#if 0 + status = RT->SetVariable(L"GRUB_ENV", &SHIM_GUID, + EFI_VARIABLE_NON_VOLATILE | + EFI_VARIABLE_BOOTSERVICE_ACCESS | + EFI_VARIABLE_RUNTIME_ACCESS, + sizeof(grubenv)-1, grubenv); + if (EFI_ERROR(status)) + Print(L"SetVariable(GRUB_ENV) failed: %r\n", status); +#endif + + return EFI_SUCCESS; +} diff --git a/gnu-efi/bootloader/Makefile b/gnu-efi/bootloader/Makefile new file mode 100644 index 0000000..98bd68d --- /dev/null +++ b/gnu-efi/bootloader/Makefile @@ -0,0 +1,93 @@ +# +# Copyright (C) 1999-2001 Hewlett-Packard Co. +# Contributed by David Mosberger +# Contributed by Stephane Eranian +# +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following +# disclaimer in the documentation and/or other materials +# provided with the distribution. +# * Neither the name of Hewlett-Packard Co. nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND +# CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +# INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS +# BE LIABLE FOR ANYDIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, +# OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR +# TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF +# THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. +# + +SRCDIR = . + +VPATH = $(SRCDIR) + +include $(SRCDIR)/../Make.defaults + +TOPDIR = $(SRCDIR)/.. + +CDIR=$(TOPDIR)/.. +LINUX_HEADERS = /usr/src/sys/build +CPPFLAGS += -D__KERNEL__ -I$(LINUX_HEADERS)/include +CRTOBJS = ../gnuefi/crt0-efi-$(ARCH).o + +LDSCRIPT = $(TOPDIR)/gnuefi/elf_$(ARCH)_efi.lds +ifneq (,$(findstring FreeBSD,$(OS))) +LDSCRIPT = $(TOPDIR)/gnuefi/elf_$(ARCH)_fbsd_efi.lds +endif + +LDFLAGS += -shared -Bsymbolic -L../lib -L../gnuefi $(CRTOBJS) + +LOADLIBES += -lefi -lgnuefi +LOADLIBES += $(LIBGCC) +LOADLIBES += -T $(LDSCRIPT) + +TARGET_APPS = main.efi +TARGET_BSDRIVERS = +TARGET_RTDRIVERS = + +ifneq ($(HAVE_EFI_OBJCOPY),) + +FORMAT := --target efi-app-$(ARCH) +$(TARGET_BSDRIVERS): FORMAT=--target efi-bsdrv-$(ARCH) +$(TARGET_RTDRIVERS): FORMAT=--target efi-rtdrv-$(ARCH) + +else + +SUBSYSTEM := 0xa +$(TARGET_BSDRIVERS): SUBSYSTEM = 0xb +$(TARGET_RTDRIVERS): SUBSYSTEM = 0xc + +FORMAT := -O binary +LDFLAGS += --defsym=EFI_SUBSYSTEM=$(SUBSYSTEM) + +endif + +TARGETS = $(TARGET_APPS) $(TARGET_BSDRIVERS) $(TARGET_RTDRIVERS) + +CFLAGS += -Wno-error=unused-parameter -Wno-error=unused-variable + +all: $(TARGETS) + +clean: + rm -f $(TARGETS) *~ *.o *.so + +.PHONY: install + +include $(SRCDIR)/../Make.rules diff --git a/gnu-efi/bootloader/main.c b/gnu-efi/bootloader/main.c new file mode 100644 index 0000000..566814e --- /dev/null +++ b/gnu-efi/bootloader/main.c @@ -0,0 +1,214 @@ +#include +#include +#include + +typedef unsigned long long size_t; + +typedef struct { + void* BaseAddress; + size_t BufferSize; + unsigned int Width; + unsigned int Height; + unsigned int PixelsPerScanline; +} Framebuffer; + +#define PSF1_MAGIC0 0x36 +#define PSF1_MAGIC1 0x04 + +typedef struct { + unsigned char magic[2]; + unsigned char mode; + unsigned char charsize; +} PSF1_HEADER; + +typedef struct { + PSF1_HEADER* psf1_Header; + void* glyphBuffer; +} PSF1_FONT; + +Framebuffer framebuffer; +Framebuffer* InitializeGOP() { + EFI_GUID gopGuid = EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID; + EFI_GRAPHICS_OUTPUT_PROTOCOL* gop; + EFI_STATUS status; + + status = uefi_call_wrapper(BS->LocateProtocol, 3, &gopGuid, NULL, (void**)&gop); + if (EFI_ERROR(status)) { + Print(L"FATAL ERROR: Unable to locate GOP\n\r"); + return NULL; + } else { + Print(L"GOP located!\n\r"); + } + + framebuffer.BaseAddress = (void*)gop->Mode->FrameBufferBase; + framebuffer.BufferSize = gop->Mode->FrameBufferSize; + framebuffer.Width = gop->Mode->Info->HorizontalResolution; + framebuffer.Height = gop->Mode->Info->VerticalResolution; + framebuffer.PixelsPerScanline = gop->Mode->Info->PixelsPerScanLine; + + return &framebuffer; +} + +EFI_FILE* LoadFile(EFI_FILE* Directory, CHAR16* Path, EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE* SystemTable){ + EFI_FILE* LoadedFile; + + EFI_LOADED_IMAGE_PROTOCOL* LoadedImage; + SystemTable->BootServices->HandleProtocol(ImageHandle, &gEfiLoadedImageProtocolGuid, (void**)&LoadedImage); + + EFI_SIMPLE_FILE_SYSTEM_PROTOCOL* FileSystem; + SystemTable->BootServices->HandleProtocol(LoadedImage->DeviceHandle, &gEfiSimpleFileSystemProtocolGuid, (void**)&FileSystem); + + if (Directory == NULL){ + FileSystem->OpenVolume(FileSystem, &Directory); + } + + EFI_STATUS s = Directory->Open(Directory, &LoadedFile, Path, EFI_FILE_MODE_READ, EFI_FILE_READ_ONLY); + if (s != EFI_SUCCESS){ + return NULL; + } + return LoadedFile; + +} + +PSF1_FONT* LoadPSF1Font(EFI_FILE* Directory, CHAR16* Path, EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE* SystemTable) { + EFI_FILE* font = LoadFile(Directory, Path, ImageHandle, SystemTable); + if (font == NULL) return NULL; + + // load the font's header into memory + PSF1_HEADER* fontHeader; + SystemTable->BootServices->AllocatePool(EfiLoaderData, sizeof(PSF1_HEADER), (void**)&fontHeader); + UINTN size = sizeof(PSF1_HEADER); + font->Read(font, &size, fontHeader); + + // check if its actually even a PSF1 font. + if (fontHeader->magic[0] != PSF1_MAGIC0 || fontHeader->magic[1] != PSF1_MAGIC1) { + return NULL; + } + + UINTN glyphBufferSize = fontHeader->charsize * 256; + if (fontHeader->mode == 1) { // 512 glyph mode + glyphBufferSize = fontHeader->charsize * 512; + } + + void* glyphBuffer; + { + font->SetPosition(font, sizeof(PSF1_HEADER)); + SystemTable->BootServices->AllocatePool(EfiLoaderData, glyphBufferSize, (void**)&glyphBuffer); + font->Read(font, &glyphBufferSize, glyphBuffer); + } + + PSF1_FONT* finishedFont; + SystemTable->BootServices->AllocatePool(EfiLoaderData, sizeof(PSF1_FONT), (void**)&finishedFont); + finishedFont->psf1_Header = fontHeader; + finishedFont->glyphBuffer = glyphBuffer; + return finishedFont; +} + +int memcmp(const void* aptr, const void* bptr, size_t n){ + const unsigned char* a = aptr, *b = bptr; + for (size_t i = 0; i < n; i++){ + if (a[i] < b[i]) return -1; + else if (a[i] > b[i]) return 1; + } + return 0; +} + +EFI_STATUS efi_main (EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE* SystemTable) { + + // sets up UEFI environment to be able to use + // certain commands + InitializeLib(ImageHandle, SystemTable); + Print(L"=== SplenkOS V2 ===\n\n\r"); + Print(L"Searching for kernel.elf...\n\r"); + + EFI_FILE* Kernel = LoadFile(NULL, L"kernel.elf", ImageHandle, SystemTable); + // we're pretty screwed + if (Kernel == NULL) { + + Print(L"FATAL ERROR: Could not load kernel! kernel.elf was not found in the root of the filesystem.\n\r"); + } else { + Print(L"Found kernel.elf!\n\r"); + } + + Elf64_Ehdr header; + { + UINTN FileInfoSize; + EFI_FILE_INFO* FileInfo; + Kernel->GetInfo(Kernel, &gEfiFileInfoGuid, &FileInfoSize, NULL); + SystemTable->BootServices->AllocatePool(EfiLoaderData, FileInfoSize, (void**)&FileInfo); + Kernel->GetInfo(Kernel, &gEfiFileInfoGuid, &FileInfoSize, (void**)&FileInfo); + + UINTN size = sizeof(header); + Kernel->Read(Kernel, &size, &header); + } + + if ( + memcmp(&header.e_ident[EI_MAG0], ELFMAG, SELFMAG) != 0 || + header.e_ident[EI_CLASS] != ELFCLASS64 || + header.e_ident[EI_DATA] != ELFDATA2LSB || + header.e_type != ET_EXEC || + header.e_machine != EM_X86_64 || + header.e_version != EV_CURRENT + ) + { + Print(L"FATAL ERROR: Kernel format is bad.\n\r"); + } + else + { + Print(L"Kernel header successfully verified.\n\r"); + } + + Elf64_Phdr* phdrs; + { + Kernel->SetPosition(Kernel, header.e_phoff); + UINTN size = header.e_phnum * header.e_phentsize; + SystemTable->BootServices->AllocatePool(EfiLoaderData, size, (void**)&phdrs); + Kernel->Read(Kernel, &size, phdrs); + } + + // loop over all the headers + for ( + Elf64_Phdr* phdr = phdrs; + (char*)phdr < (char*)phdrs + header.e_phnum * header.e_phentsize; + phdr = (Elf64_Phdr*)((char*)phdr + header.e_phentsize) + ) + { + switch (phdr->p_type) { + case PT_LOAD: + { + int pages = (phdr->p_memsz * 0x1000 - 1) / 0x1000; + Elf64_Addr segment = phdr->p_paddr; + SystemTable->BootServices->AllocatePages(AllocateAddress, EfiLoaderData, pages, &segment); + + Kernel->SetPosition(Kernel, phdr->p_offset); + UINTN size = phdr->p_filesz; + Kernel->Read(Kernel, &size, (void*)segment); + break; + } + } + } + + Print(L"Kernel loaded!\n\r"); + + // Run the kernel's main function! :D + void (*KernelStart)(Framebuffer*, PSF1_FONT*) = ((__attribute__((sysv_abi)) void (*)(Framebuffer*, PSF1_FONT*) ) header.e_entry); + + PSF1_FONT* newFont = LoadPSF1Font(NULL, L"zap-light18.psf", ImageHandle, SystemTable); + if (newFont == NULL) { + Print(L"Font is invalid or wasn't found.\n\r"); + } else { + Print(L"Found font! char size = %d\n\r", newFont->psf1_Header->charsize); + } + + Framebuffer* newBuffer = InitializeGOP(); // setup graphics output protocol and screen + Print(L" - Base: 0x%x\n\r - Size: 0x%x\n\r - Width: %d\n\r - Height: %d\n\r - PixelsPerScanline: %d\n\r\n\r", + newBuffer->BaseAddress, + newBuffer->BufferSize, + newBuffer->Width, + newBuffer->Height, + newBuffer->PixelsPerScanline); + + KernelStart(newBuffer, newFont); + + return EFI_SUCCESS; // Exit the UEFI application +} diff --git a/gnu-efi/git folder/COMMIT_EDITMSG b/gnu-efi/git folder/COMMIT_EDITMSG new file mode 100644 index 0000000..4f274ed --- /dev/null +++ b/gnu-efi/git folder/COMMIT_EDITMSG @@ -0,0 +1,11 @@ +load psf1 font +# Please enter the commit message for your changes. Lines starting +# with '#' will be ignored, and an empty message aborts the commit. +# +# On branch main +# Your branch is up to date with 'origin/main'. +# +# Changes to be committed: +# modified: bootloader/main.c +# modified: x86_64/bootloader/main.efi +# diff --git a/gnu-efi/git folder/FETCH_HEAD b/gnu-efi/git folder/FETCH_HEAD new file mode 100644 index 0000000..83edb05 --- /dev/null +++ b/gnu-efi/git folder/FETCH_HEAD @@ -0,0 +1 @@ +76da8603cc06ab15c5e32773ea77ccdafc4674b7 branch 'main' of https://github.com/SpookyDervish/gnu-efi diff --git a/gnu-efi/git folder/HEAD b/gnu-efi/git folder/HEAD new file mode 100644 index 0000000..b870d82 --- /dev/null +++ b/gnu-efi/git folder/HEAD @@ -0,0 +1 @@ +ref: refs/heads/main diff --git a/gnu-efi/git folder/ORIG_HEAD b/gnu-efi/git folder/ORIG_HEAD new file mode 100644 index 0000000..08f04cb --- /dev/null +++ b/gnu-efi/git folder/ORIG_HEAD @@ -0,0 +1 @@ +76da8603cc06ab15c5e32773ea77ccdafc4674b7 diff --git a/gnu-efi/git folder/config b/gnu-efi/git folder/config new file mode 100644 index 0000000..862547b --- /dev/null +++ b/gnu-efi/git folder/config @@ -0,0 +1,15 @@ +[core] + repositoryformatversion = 0 + filemode = true + bare = false + logallrefupdates = true +[remote "upstream"] + url = https://github.com/Absurdponcho/gnu-efi + fetch = +refs/heads/*:refs/remotes/upstream/* +[branch "main"] + remote = origin + vscode-merge-base = origin/main + merge = refs/heads/main +[remote "origin"] + url = https://github.com/SpookyDervish/gnu-efi.git + fetch = +refs/heads/*:refs/remotes/origin/* diff --git a/gnu-efi/git folder/description b/gnu-efi/git folder/description new file mode 100644 index 0000000..498b267 --- /dev/null +++ b/gnu-efi/git folder/description @@ -0,0 +1 @@ +Unnamed repository; edit this file 'description' to name the repository. diff --git a/gnu-efi/git folder/hooks/applypatch-msg.sample b/gnu-efi/git folder/hooks/applypatch-msg.sample new file mode 100755 index 0000000..a5d7b84 --- /dev/null +++ b/gnu-efi/git folder/hooks/applypatch-msg.sample @@ -0,0 +1,15 @@ +#!/bin/sh +# +# An example hook script to check the commit log message taken by +# applypatch from an e-mail message. +# +# The hook should exit with non-zero status after issuing an +# appropriate message if it wants to stop the commit. The hook is +# allowed to edit the commit message file. +# +# To enable this hook, rename this file to "applypatch-msg". + +. git-sh-setup +commitmsg="$(git rev-parse --git-path hooks/commit-msg)" +test -x "$commitmsg" && exec "$commitmsg" ${1+"$@"} +: diff --git a/gnu-efi/git folder/hooks/commit-msg.sample b/gnu-efi/git folder/hooks/commit-msg.sample new file mode 100755 index 0000000..b58d118 --- /dev/null +++ b/gnu-efi/git folder/hooks/commit-msg.sample @@ -0,0 +1,24 @@ +#!/bin/sh +# +# An example hook script to check the commit log message. +# Called by "git commit" with one argument, the name of the file +# that has the commit message. The hook should exit with non-zero +# status after issuing an appropriate message if it wants to stop the +# commit. The hook is allowed to edit the commit message file. +# +# To enable this hook, rename this file to "commit-msg". + +# Uncomment the below to add a Signed-off-by line to the message. +# Doing this in a hook is a bad idea in general, but the prepare-commit-msg +# hook is more suited to it. +# +# SOB=$(git var GIT_AUTHOR_IDENT | sed -n 's/^\(.*>\).*$/Signed-off-by: \1/p') +# grep -qs "^$SOB" "$1" || echo "$SOB" >> "$1" + +# This example catches duplicate Signed-off-by lines. + +test "" = "$(grep '^Signed-off-by: ' "$1" | + sort | uniq -c | sed -e '/^[ ]*1[ ]/d')" || { + echo >&2 Duplicate Signed-off-by lines. + exit 1 +} diff --git a/gnu-efi/git folder/hooks/fsmonitor-watchman.sample b/gnu-efi/git folder/hooks/fsmonitor-watchman.sample new file mode 100755 index 0000000..23e856f --- /dev/null +++ b/gnu-efi/git folder/hooks/fsmonitor-watchman.sample @@ -0,0 +1,174 @@ +#!/usr/bin/perl + +use strict; +use warnings; +use IPC::Open2; + +# An example hook script to integrate Watchman +# (https://facebook.github.io/watchman/) with git to speed up detecting +# new and modified files. +# +# The hook is passed a version (currently 2) and last update token +# formatted as a string and outputs to stdout a new update token and +# all files that have been modified since the update token. Paths must +# be relative to the root of the working tree and separated by a single NUL. +# +# To enable this hook, rename this file to "query-watchman" and set +# 'git config core.fsmonitor .git/hooks/query-watchman' +# +my ($version, $last_update_token) = @ARGV; + +# Uncomment for debugging +# print STDERR "$0 $version $last_update_token\n"; + +# Check the hook interface version +if ($version ne 2) { + die "Unsupported query-fsmonitor hook version '$version'.\n" . + "Falling back to scanning...\n"; +} + +my $git_work_tree = get_working_dir(); + +my $retry = 1; + +my $json_pkg; +eval { + require JSON::XS; + $json_pkg = "JSON::XS"; + 1; +} or do { + require JSON::PP; + $json_pkg = "JSON::PP"; +}; + +launch_watchman(); + +sub launch_watchman { + my $o = watchman_query(); + if (is_work_tree_watched($o)) { + output_result($o->{clock}, @{$o->{files}}); + } +} + +sub output_result { + my ($clockid, @files) = @_; + + # Uncomment for debugging watchman output + # open (my $fh, ">", ".git/watchman-output.out"); + # binmode $fh, ":utf8"; + # print $fh "$clockid\n@files\n"; + # close $fh; + + binmode STDOUT, ":utf8"; + print $clockid; + print "\0"; + local $, = "\0"; + print @files; +} + +sub watchman_clock { + my $response = qx/watchman clock "$git_work_tree"/; + die "Failed to get clock id on '$git_work_tree'.\n" . + "Falling back to scanning...\n" if $? != 0; + + return $json_pkg->new->utf8->decode($response); +} + +sub watchman_query { + my $pid = open2(\*CHLD_OUT, \*CHLD_IN, 'watchman -j --no-pretty') + or die "open2() failed: $!\n" . + "Falling back to scanning...\n"; + + # In the query expression below we're asking for names of files that + # changed since $last_update_token but not from the .git folder. + # + # To accomplish this, we're using the "since" generator to use the + # recency index to select candidate nodes and "fields" to limit the + # output to file names only. Then we're using the "expression" term to + # further constrain the results. + my $last_update_line = ""; + if (substr($last_update_token, 0, 1) eq "c") { + $last_update_token = "\"$last_update_token\""; + $last_update_line = qq[\n"since": $last_update_token,]; + } + my $query = <<" END"; + ["query", "$git_work_tree", {$last_update_line + "fields": ["name"], + "expression": ["not", ["dirname", ".git"]] + }] + END + + # Uncomment for debugging the watchman query + # open (my $fh, ">", ".git/watchman-query.json"); + # print $fh $query; + # close $fh; + + print CHLD_IN $query; + close CHLD_IN; + my $response = do {local $/; }; + + # Uncomment for debugging the watch response + # open ($fh, ">", ".git/watchman-response.json"); + # print $fh $response; + # close $fh; + + die "Watchman: command returned no output.\n" . + "Falling back to scanning...\n" if $response eq ""; + die "Watchman: command returned invalid output: $response\n" . + "Falling back to scanning...\n" unless $response =~ /^\{/; + + return $json_pkg->new->utf8->decode($response); +} + +sub is_work_tree_watched { + my ($output) = @_; + my $error = $output->{error}; + if ($retry > 0 and $error and $error =~ m/unable to resolve root .* directory (.*) is not watched/) { + $retry--; + my $response = qx/watchman watch "$git_work_tree"/; + die "Failed to make watchman watch '$git_work_tree'.\n" . + "Falling back to scanning...\n" if $? != 0; + $output = $json_pkg->new->utf8->decode($response); + $error = $output->{error}; + die "Watchman: $error.\n" . + "Falling back to scanning...\n" if $error; + + # Uncomment for debugging watchman output + # open (my $fh, ">", ".git/watchman-output.out"); + # close $fh; + + # Watchman will always return all files on the first query so + # return the fast "everything is dirty" flag to git and do the + # Watchman query just to get it over with now so we won't pay + # the cost in git to look up each individual file. + my $o = watchman_clock(); + $error = $output->{error}; + + die "Watchman: $error.\n" . + "Falling back to scanning...\n" if $error; + + output_result($o->{clock}, ("/")); + $last_update_token = $o->{clock}; + + eval { launch_watchman() }; + return 0; + } + + die "Watchman: $error.\n" . + "Falling back to scanning...\n" if $error; + + return 1; +} + +sub get_working_dir { + my $working_dir; + if ($^O =~ 'msys' || $^O =~ 'cygwin') { + $working_dir = Win32::GetCwd(); + $working_dir =~ tr/\\/\//; + } else { + require Cwd; + $working_dir = Cwd::cwd(); + } + + return $working_dir; +} diff --git a/gnu-efi/git folder/hooks/post-update.sample b/gnu-efi/git folder/hooks/post-update.sample new file mode 100755 index 0000000..ec17ec1 --- /dev/null +++ b/gnu-efi/git folder/hooks/post-update.sample @@ -0,0 +1,8 @@ +#!/bin/sh +# +# An example hook script to prepare a packed repository for use over +# dumb transports. +# +# To enable this hook, rename this file to "post-update". + +exec git update-server-info diff --git a/gnu-efi/git folder/hooks/pre-applypatch.sample b/gnu-efi/git folder/hooks/pre-applypatch.sample new file mode 100755 index 0000000..4142082 --- /dev/null +++ b/gnu-efi/git folder/hooks/pre-applypatch.sample @@ -0,0 +1,14 @@ +#!/bin/sh +# +# An example hook script to verify what is about to be committed +# by applypatch from an e-mail message. +# +# The hook should exit with non-zero status after issuing an +# appropriate message if it wants to stop the commit. +# +# To enable this hook, rename this file to "pre-applypatch". + +. git-sh-setup +precommit="$(git rev-parse --git-path hooks/pre-commit)" +test -x "$precommit" && exec "$precommit" ${1+"$@"} +: diff --git a/gnu-efi/git folder/hooks/pre-commit.sample b/gnu-efi/git folder/hooks/pre-commit.sample new file mode 100755 index 0000000..29ed5ee --- /dev/null +++ b/gnu-efi/git folder/hooks/pre-commit.sample @@ -0,0 +1,49 @@ +#!/bin/sh +# +# An example hook script to verify what is about to be committed. +# Called by "git commit" with no arguments. The hook should +# exit with non-zero status after issuing an appropriate message if +# it wants to stop the commit. +# +# To enable this hook, rename this file to "pre-commit". + +if git rev-parse --verify HEAD >/dev/null 2>&1 +then + against=HEAD +else + # Initial commit: diff against an empty tree object + against=$(git hash-object -t tree /dev/null) +fi + +# If you want to allow non-ASCII filenames set this variable to true. +allownonascii=$(git config --type=bool hooks.allownonascii) + +# Redirect output to stderr. +exec 1>&2 + +# Cross platform projects tend to avoid non-ASCII filenames; prevent +# them from being added to the repository. We exploit the fact that the +# printable range starts at the space character and ends with tilde. +if [ "$allownonascii" != "true" ] && + # Note that the use of brackets around a tr range is ok here, (it's + # even required, for portability to Solaris 10's /usr/bin/tr), since + # the square bracket bytes happen to fall in the designated range. + test $(git diff-index --cached --name-only --diff-filter=A -z $against | + LC_ALL=C tr -d '[ -~]\0' | wc -c) != 0 +then + cat <<\EOF +Error: Attempt to add a non-ASCII file name. + +This can cause problems if you want to work with people on other platforms. + +To be portable it is advisable to rename the file. + +If you know what you are doing you can disable this check using: + + git config hooks.allownonascii true +EOF + exit 1 +fi + +# If there are whitespace errors, print the offending file names and fail. +exec git diff-index --check --cached $against -- diff --git a/gnu-efi/git folder/hooks/pre-merge-commit.sample b/gnu-efi/git folder/hooks/pre-merge-commit.sample new file mode 100755 index 0000000..399eab1 --- /dev/null +++ b/gnu-efi/git folder/hooks/pre-merge-commit.sample @@ -0,0 +1,13 @@ +#!/bin/sh +# +# An example hook script to verify what is about to be committed. +# Called by "git merge" with no arguments. The hook should +# exit with non-zero status after issuing an appropriate message to +# stderr if it wants to stop the merge commit. +# +# To enable this hook, rename this file to "pre-merge-commit". + +. git-sh-setup +test -x "$GIT_DIR/hooks/pre-commit" && + exec "$GIT_DIR/hooks/pre-commit" +: diff --git a/gnu-efi/git folder/hooks/pre-push.sample b/gnu-efi/git folder/hooks/pre-push.sample new file mode 100755 index 0000000..4ce688d --- /dev/null +++ b/gnu-efi/git folder/hooks/pre-push.sample @@ -0,0 +1,53 @@ +#!/bin/sh + +# An example hook script to verify what is about to be pushed. Called by "git +# push" after it has checked the remote status, but before anything has been +# pushed. If this script exits with a non-zero status nothing will be pushed. +# +# This hook is called with the following parameters: +# +# $1 -- Name of the remote to which the push is being done +# $2 -- URL to which the push is being done +# +# If pushing without using a named remote those arguments will be equal. +# +# Information about the commits which are being pushed is supplied as lines to +# the standard input in the form: +# +# +# +# This sample shows how to prevent push of commits where the log message starts +# with "WIP" (work in progress). + +remote="$1" +url="$2" + +zero=$(git hash-object --stdin &2 "Found WIP commit in $local_ref, not pushing" + exit 1 + fi + fi +done + +exit 0 diff --git a/gnu-efi/git folder/hooks/pre-rebase.sample b/gnu-efi/git folder/hooks/pre-rebase.sample new file mode 100755 index 0000000..6cbef5c --- /dev/null +++ b/gnu-efi/git folder/hooks/pre-rebase.sample @@ -0,0 +1,169 @@ +#!/bin/sh +# +# Copyright (c) 2006, 2008 Junio C Hamano +# +# The "pre-rebase" hook is run just before "git rebase" starts doing +# its job, and can prevent the command from running by exiting with +# non-zero status. +# +# The hook is called with the following parameters: +# +# $1 -- the upstream the series was forked from. +# $2 -- the branch being rebased (or empty when rebasing the current branch). +# +# This sample shows how to prevent topic branches that are already +# merged to 'next' branch from getting rebased, because allowing it +# would result in rebasing already published history. + +publish=next +basebranch="$1" +if test "$#" = 2 +then + topic="refs/heads/$2" +else + topic=`git symbolic-ref HEAD` || + exit 0 ;# we do not interrupt rebasing detached HEAD +fi + +case "$topic" in +refs/heads/??/*) + ;; +*) + exit 0 ;# we do not interrupt others. + ;; +esac + +# Now we are dealing with a topic branch being rebased +# on top of master. Is it OK to rebase it? + +# Does the topic really exist? +git show-ref -q "$topic" || { + echo >&2 "No such branch $topic" + exit 1 +} + +# Is topic fully merged to master? +not_in_master=`git rev-list --pretty=oneline ^master "$topic"` +if test -z "$not_in_master" +then + echo >&2 "$topic is fully merged to master; better remove it." + exit 1 ;# we could allow it, but there is no point. +fi + +# Is topic ever merged to next? If so you should not be rebasing it. +only_next_1=`git rev-list ^master "^$topic" ${publish} | sort` +only_next_2=`git rev-list ^master ${publish} | sort` +if test "$only_next_1" = "$only_next_2" +then + not_in_topic=`git rev-list "^$topic" master` + if test -z "$not_in_topic" + then + echo >&2 "$topic is already up to date with master" + exit 1 ;# we could allow it, but there is no point. + else + exit 0 + fi +else + not_in_next=`git rev-list --pretty=oneline ^${publish} "$topic"` + /usr/bin/perl -e ' + my $topic = $ARGV[0]; + my $msg = "* $topic has commits already merged to public branch:\n"; + my (%not_in_next) = map { + /^([0-9a-f]+) /; + ($1 => 1); + } split(/\n/, $ARGV[1]); + for my $elem (map { + /^([0-9a-f]+) (.*)$/; + [$1 => $2]; + } split(/\n/, $ARGV[2])) { + if (!exists $not_in_next{$elem->[0]}) { + if ($msg) { + print STDERR $msg; + undef $msg; + } + print STDERR " $elem->[1]\n"; + } + } + ' "$topic" "$not_in_next" "$not_in_master" + exit 1 +fi + +<<\DOC_END + +This sample hook safeguards topic branches that have been +published from being rewound. + +The workflow assumed here is: + + * Once a topic branch forks from "master", "master" is never + merged into it again (either directly or indirectly). + + * Once a topic branch is fully cooked and merged into "master", + it is deleted. If you need to build on top of it to correct + earlier mistakes, a new topic branch is created by forking at + the tip of the "master". This is not strictly necessary, but + it makes it easier to keep your history simple. + + * Whenever you need to test or publish your changes to topic + branches, merge them into "next" branch. + +The script, being an example, hardcodes the publish branch name +to be "next", but it is trivial to make it configurable via +$GIT_DIR/config mechanism. + +With this workflow, you would want to know: + +(1) ... if a topic branch has ever been merged to "next". Young + topic branches can have stupid mistakes you would rather + clean up before publishing, and things that have not been + merged into other branches can be easily rebased without + affecting other people. But once it is published, you would + not want to rewind it. + +(2) ... if a topic branch has been fully merged to "master". + Then you can delete it. More importantly, you should not + build on top of it -- other people may already want to + change things related to the topic as patches against your + "master", so if you need further changes, it is better to + fork the topic (perhaps with the same name) afresh from the + tip of "master". + +Let's look at this example: + + o---o---o---o---o---o---o---o---o---o "next" + / / / / + / a---a---b A / / + / / / / + / / c---c---c---c B / + / / / \ / + / / / b---b C \ / + / / / / \ / + ---o---o---o---o---o---o---o---o---o---o---o "master" + + +A, B and C are topic branches. + + * A has one fix since it was merged up to "next". + + * B has finished. It has been fully merged up to "master" and "next", + and is ready to be deleted. + + * C has not merged to "next" at all. + +We would want to allow C to be rebased, refuse A, and encourage +B to be deleted. + +To compute (1): + + git rev-list ^master ^topic next + git rev-list ^master next + + if these match, topic has not merged in next at all. + +To compute (2): + + git rev-list master..topic + + if this is empty, it is fully merged to "master". + +DOC_END diff --git a/gnu-efi/git folder/hooks/pre-receive.sample b/gnu-efi/git folder/hooks/pre-receive.sample new file mode 100755 index 0000000..a1fd29e --- /dev/null +++ b/gnu-efi/git folder/hooks/pre-receive.sample @@ -0,0 +1,24 @@ +#!/bin/sh +# +# An example hook script to make use of push options. +# The example simply echoes all push options that start with 'echoback=' +# and rejects all pushes when the "reject" push option is used. +# +# To enable this hook, rename this file to "pre-receive". + +if test -n "$GIT_PUSH_OPTION_COUNT" +then + i=0 + while test "$i" -lt "$GIT_PUSH_OPTION_COUNT" + do + eval "value=\$GIT_PUSH_OPTION_$i" + case "$value" in + echoback=*) + echo "echo from the pre-receive-hook: ${value#*=}" >&2 + ;; + reject) + exit 1 + esac + i=$((i + 1)) + done +fi diff --git a/gnu-efi/git folder/hooks/prepare-commit-msg.sample b/gnu-efi/git folder/hooks/prepare-commit-msg.sample new file mode 100755 index 0000000..10fa14c --- /dev/null +++ b/gnu-efi/git folder/hooks/prepare-commit-msg.sample @@ -0,0 +1,42 @@ +#!/bin/sh +# +# An example hook script to prepare the commit log message. +# Called by "git commit" with the name of the file that has the +# commit message, followed by the description of the commit +# message's source. The hook's purpose is to edit the commit +# message file. If the hook fails with a non-zero status, +# the commit is aborted. +# +# To enable this hook, rename this file to "prepare-commit-msg". + +# This hook includes three examples. The first one removes the +# "# Please enter the commit message..." help message. +# +# The second includes the output of "git diff --name-status -r" +# into the message, just before the "git status" output. It is +# commented because it doesn't cope with --amend or with squashed +# commits. +# +# The third example adds a Signed-off-by line to the message, that can +# still be edited. This is rarely a good idea. + +COMMIT_MSG_FILE=$1 +COMMIT_SOURCE=$2 +SHA1=$3 + +/usr/bin/perl -i.bak -ne 'print unless(m/^. Please enter the commit message/..m/^#$/)' "$COMMIT_MSG_FILE" + +# case "$COMMIT_SOURCE,$SHA1" in +# ,|template,) +# /usr/bin/perl -i.bak -pe ' +# print "\n" . `git diff --cached --name-status -r` +# if /^#/ && $first++ == 0' "$COMMIT_MSG_FILE" ;; +# *) ;; +# esac + +# SOB=$(git var GIT_COMMITTER_IDENT | sed -n 's/^\(.*>\).*$/Signed-off-by: \1/p') +# git interpret-trailers --in-place --trailer "$SOB" "$COMMIT_MSG_FILE" +# if test -z "$COMMIT_SOURCE" +# then +# /usr/bin/perl -i.bak -pe 'print "\n" if !$first_line++' "$COMMIT_MSG_FILE" +# fi diff --git a/gnu-efi/git folder/hooks/push-to-checkout.sample b/gnu-efi/git folder/hooks/push-to-checkout.sample new file mode 100755 index 0000000..af5a0c0 --- /dev/null +++ b/gnu-efi/git folder/hooks/push-to-checkout.sample @@ -0,0 +1,78 @@ +#!/bin/sh + +# An example hook script to update a checked-out tree on a git push. +# +# This hook is invoked by git-receive-pack(1) when it reacts to git +# push and updates reference(s) in its repository, and when the push +# tries to update the branch that is currently checked out and the +# receive.denyCurrentBranch configuration variable is set to +# updateInstead. +# +# By default, such a push is refused if the working tree and the index +# of the remote repository has any difference from the currently +# checked out commit; when both the working tree and the index match +# the current commit, they are updated to match the newly pushed tip +# of the branch. This hook is to be used to override the default +# behaviour; however the code below reimplements the default behaviour +# as a starting point for convenient modification. +# +# The hook receives the commit with which the tip of the current +# branch is going to be updated: +commit=$1 + +# It can exit with a non-zero status to refuse the push (when it does +# so, it must not modify the index or the working tree). +die () { + echo >&2 "$*" + exit 1 +} + +# Or it can make any necessary changes to the working tree and to the +# index to bring them to the desired state when the tip of the current +# branch is updated to the new commit, and exit with a zero status. +# +# For example, the hook can simply run git read-tree -u -m HEAD "$1" +# in order to emulate git fetch that is run in the reverse direction +# with git push, as the two-tree form of git read-tree -u -m is +# essentially the same as git switch or git checkout that switches +# branches while keeping the local changes in the working tree that do +# not interfere with the difference between the branches. + +# The below is a more-or-less exact translation to shell of the C code +# for the default behaviour for git's push-to-checkout hook defined in +# the push_to_deploy() function in builtin/receive-pack.c. +# +# Note that the hook will be executed from the repository directory, +# not from the working tree, so if you want to perform operations on +# the working tree, you will have to adapt your code accordingly, e.g. +# by adding "cd .." or using relative paths. + +if ! git update-index -q --ignore-submodules --refresh +then + die "Up-to-date check failed" +fi + +if ! git diff-files --quiet --ignore-submodules -- +then + die "Working directory has unstaged changes" +fi + +# This is a rough translation of: +# +# head_has_history() ? "HEAD" : EMPTY_TREE_SHA1_HEX +if git cat-file -e HEAD 2>/dev/null +then + head=HEAD +else + head=$(git hash-object -t tree --stdin &2 + exit 1 +} + +unset GIT_DIR GIT_WORK_TREE +cd "$worktree" && + +if grep -q "^diff --git " "$1" +then + validate_patch "$1" +else + validate_cover_letter "$1" +fi && + +if test "$GIT_SENDEMAIL_FILE_COUNTER" = "$GIT_SENDEMAIL_FILE_TOTAL" +then + git config --unset-all sendemail.validateWorktree && + trap 'git worktree remove -ff "$worktree"' EXIT && + validate_series +fi diff --git a/gnu-efi/git folder/hooks/update.sample b/gnu-efi/git folder/hooks/update.sample new file mode 100755 index 0000000..c4d426b --- /dev/null +++ b/gnu-efi/git folder/hooks/update.sample @@ -0,0 +1,128 @@ +#!/bin/sh +# +# An example hook script to block unannotated tags from entering. +# Called by "git receive-pack" with arguments: refname sha1-old sha1-new +# +# To enable this hook, rename this file to "update". +# +# Config +# ------ +# hooks.allowunannotated +# This boolean sets whether unannotated tags will be allowed into the +# repository. By default they won't be. +# hooks.allowdeletetag +# This boolean sets whether deleting tags will be allowed in the +# repository. By default they won't be. +# hooks.allowmodifytag +# This boolean sets whether a tag may be modified after creation. By default +# it won't be. +# hooks.allowdeletebranch +# This boolean sets whether deleting branches will be allowed in the +# repository. By default they won't be. +# hooks.denycreatebranch +# This boolean sets whether remotely creating branches will be denied +# in the repository. By default this is allowed. +# + +# --- Command line +refname="$1" +oldrev="$2" +newrev="$3" + +# --- Safety check +if [ -z "$GIT_DIR" ]; then + echo "Don't run this script from the command line." >&2 + echo " (if you want, you could supply GIT_DIR then run" >&2 + echo " $0 )" >&2 + exit 1 +fi + +if [ -z "$refname" -o -z "$oldrev" -o -z "$newrev" ]; then + echo "usage: $0 " >&2 + exit 1 +fi + +# --- Config +allowunannotated=$(git config --type=bool hooks.allowunannotated) +allowdeletebranch=$(git config --type=bool hooks.allowdeletebranch) +denycreatebranch=$(git config --type=bool hooks.denycreatebranch) +allowdeletetag=$(git config --type=bool hooks.allowdeletetag) +allowmodifytag=$(git config --type=bool hooks.allowmodifytag) + +# check for no description +projectdesc=$(sed -e '1q' "$GIT_DIR/description") +case "$projectdesc" in +"Unnamed repository"* | "") + echo "*** Project description file hasn't been set" >&2 + exit 1 + ;; +esac + +# --- Check types +# if $newrev is 0000...0000, it's a commit to delete a ref. +zero=$(git hash-object --stdin &2 + echo "*** Use 'git tag [ -a | -s ]' for tags you want to propagate." >&2 + exit 1 + fi + ;; + refs/tags/*,delete) + # delete tag + if [ "$allowdeletetag" != "true" ]; then + echo "*** Deleting a tag is not allowed in this repository" >&2 + exit 1 + fi + ;; + refs/tags/*,tag) + # annotated tag + if [ "$allowmodifytag" != "true" ] && git rev-parse $refname > /dev/null 2>&1 + then + echo "*** Tag '$refname' already exists." >&2 + echo "*** Modifying a tag is not allowed in this repository." >&2 + exit 1 + fi + ;; + refs/heads/*,commit) + # branch + if [ "$oldrev" = "$zero" -a "$denycreatebranch" = "true" ]; then + echo "*** Creating a branch is not allowed in this repository" >&2 + exit 1 + fi + ;; + refs/heads/*,delete) + # delete branch + if [ "$allowdeletebranch" != "true" ]; then + echo "*** Deleting a branch is not allowed in this repository" >&2 + exit 1 + fi + ;; + refs/remotes/*,commit) + # tracking branch + ;; + refs/remotes/*,delete) + # delete tracking branch + if [ "$allowdeletebranch" != "true" ]; then + echo "*** Deleting a tracking branch is not allowed in this repository" >&2 + exit 1 + fi + ;; + *) + # Anything else (is there anything else?) + echo "*** Update hook: unknown type of update to ref $refname of type $newrev_type" >&2 + exit 1 + ;; +esac + +# --- Finished +exit 0 diff --git a/gnu-efi/git folder/index b/gnu-efi/git folder/index new file mode 100644 index 0000000..3796e73 Binary files /dev/null and b/gnu-efi/git folder/index differ diff --git a/gnu-efi/git folder/info/exclude b/gnu-efi/git folder/info/exclude new file mode 100644 index 0000000..a5196d1 --- /dev/null +++ b/gnu-efi/git folder/info/exclude @@ -0,0 +1,6 @@ +# git ls-files --others --exclude-from=.git/info/exclude +# Lines that start with '#' are comments. +# For a project mostly in C, the following would be a good set of +# exclude patterns (uncomment them if you want to use them): +# *.[oa] +# *~ diff --git a/gnu-efi/git folder/logs/HEAD b/gnu-efi/git folder/logs/HEAD new file mode 100644 index 0000000..e44b76f --- /dev/null +++ b/gnu-efi/git folder/logs/HEAD @@ -0,0 +1,8 @@ +0000000000000000000000000000000000000000 cd81680b0137b18bdb82d547a34feb7bf2cb6837 SpookyDervish 1769496422 +1100 clone: from https://github.com/Absurdponcho/gnu-efi +cd81680b0137b18bdb82d547a34feb7bf2cb6837 71be5b9347fb34e8ab0030a0344005d5c9bc55d7 SpookyDervish 1769498252 +1100 commit: build +71be5b9347fb34e8ab0030a0344005d5c9bc55d7 07a56403494bfe4b3c7d3813d7c191b1135b71ca SpookyDervish 1769502848 +1100 commit: check kernel efi header +07a56403494bfe4b3c7d3813d7c191b1135b71ca 0e72223057bd8970c8d642cbbfaa055aacdd5464 SpookyDervish 1769503655 +1100 commit: load kernel with bootloader +0e72223057bd8970c8d642cbbfaa055aacdd5464 d19573fdb9dc263ffee7e9323845b78b7535dbe1 SpookyDervish 1769505269 +1100 commit: initialize GOP +d19573fdb9dc263ffee7e9323845b78b7535dbe1 972d2c8bc3086b65f45bcff9684fbda6ab73cd47 SpookyDervish 1769506611 +1100 commit: get gop framebuffer data +972d2c8bc3086b65f45bcff9684fbda6ab73cd47 0ecf403f47dc5b61e1c5a7b9f1e3cbd710082bff SpookyDervish 1769508256 +1100 commit: pass framebuffer to kernel +0ecf403f47dc5b61e1c5a7b9f1e3cbd710082bff 76da8603cc06ab15c5e32773ea77ccdafc4674b7 SpookyDervish 1769509888 +1100 commit: load psf1 font diff --git a/gnu-efi/git folder/logs/refs/heads/main b/gnu-efi/git folder/logs/refs/heads/main new file mode 100644 index 0000000..e44b76f --- /dev/null +++ b/gnu-efi/git folder/logs/refs/heads/main @@ -0,0 +1,8 @@ +0000000000000000000000000000000000000000 cd81680b0137b18bdb82d547a34feb7bf2cb6837 SpookyDervish 1769496422 +1100 clone: from https://github.com/Absurdponcho/gnu-efi +cd81680b0137b18bdb82d547a34feb7bf2cb6837 71be5b9347fb34e8ab0030a0344005d5c9bc55d7 SpookyDervish 1769498252 +1100 commit: build +71be5b9347fb34e8ab0030a0344005d5c9bc55d7 07a56403494bfe4b3c7d3813d7c191b1135b71ca SpookyDervish 1769502848 +1100 commit: check kernel efi header +07a56403494bfe4b3c7d3813d7c191b1135b71ca 0e72223057bd8970c8d642cbbfaa055aacdd5464 SpookyDervish 1769503655 +1100 commit: load kernel with bootloader +0e72223057bd8970c8d642cbbfaa055aacdd5464 d19573fdb9dc263ffee7e9323845b78b7535dbe1 SpookyDervish 1769505269 +1100 commit: initialize GOP +d19573fdb9dc263ffee7e9323845b78b7535dbe1 972d2c8bc3086b65f45bcff9684fbda6ab73cd47 SpookyDervish 1769506611 +1100 commit: get gop framebuffer data +972d2c8bc3086b65f45bcff9684fbda6ab73cd47 0ecf403f47dc5b61e1c5a7b9f1e3cbd710082bff SpookyDervish 1769508256 +1100 commit: pass framebuffer to kernel +0ecf403f47dc5b61e1c5a7b9f1e3cbd710082bff 76da8603cc06ab15c5e32773ea77ccdafc4674b7 SpookyDervish 1769509888 +1100 commit: load psf1 font diff --git a/gnu-efi/git folder/logs/refs/remotes/origin/HEAD b/gnu-efi/git folder/logs/refs/remotes/origin/HEAD new file mode 100644 index 0000000..1c0f7db --- /dev/null +++ b/gnu-efi/git folder/logs/refs/remotes/origin/HEAD @@ -0,0 +1 @@ +0000000000000000000000000000000000000000 07a56403494bfe4b3c7d3813d7c191b1135b71ca SpookyDervish 1769502937 +1100 fetch diff --git a/gnu-efi/git folder/logs/refs/remotes/origin/main b/gnu-efi/git folder/logs/refs/remotes/origin/main new file mode 100644 index 0000000..855d241 --- /dev/null +++ b/gnu-efi/git folder/logs/refs/remotes/origin/main @@ -0,0 +1,7 @@ +0000000000000000000000000000000000000000 cd81680b0137b18bdb82d547a34feb7bf2cb6837 SpookyDervish 1769502860 +1100 fetch origin main: storing head +cd81680b0137b18bdb82d547a34feb7bf2cb6837 07a56403494bfe4b3c7d3813d7c191b1135b71ca SpookyDervish 1769502862 +1100 update by push +07a56403494bfe4b3c7d3813d7c191b1135b71ca 0e72223057bd8970c8d642cbbfaa055aacdd5464 SpookyDervish 1769503670 +1100 update by push +0e72223057bd8970c8d642cbbfaa055aacdd5464 d19573fdb9dc263ffee7e9323845b78b7535dbe1 SpookyDervish 1769505277 +1100 update by push +d19573fdb9dc263ffee7e9323845b78b7535dbe1 972d2c8bc3086b65f45bcff9684fbda6ab73cd47 SpookyDervish 1769506620 +1100 update by push +972d2c8bc3086b65f45bcff9684fbda6ab73cd47 0ecf403f47dc5b61e1c5a7b9f1e3cbd710082bff SpookyDervish 1769508283 +1100 update by push +0ecf403f47dc5b61e1c5a7b9f1e3cbd710082bff 76da8603cc06ab15c5e32773ea77ccdafc4674b7 SpookyDervish 1769509906 +1100 update by push diff --git a/gnu-efi/git folder/logs/refs/remotes/upstream/HEAD b/gnu-efi/git folder/logs/refs/remotes/upstream/HEAD new file mode 100644 index 0000000..f872caf --- /dev/null +++ b/gnu-efi/git folder/logs/refs/remotes/upstream/HEAD @@ -0,0 +1,2 @@ +0000000000000000000000000000000000000000 cd81680b0137b18bdb82d547a34feb7bf2cb6837 SpookyDervish 1769496422 +1100 clone: from https://github.com/Absurdponcho/gnu-efi +0000000000000000000000000000000000000000 0000000000000000000000000000000000000000 Nathaniel 1769502859 +1100 remote: renamed refs/remotes/origin/HEAD to refs/remotes/upstream/HEAD diff --git a/gnu-efi/git folder/objects/00/1ef10cbff8a9a485b09c7f0caf58cab2d053ce b/gnu-efi/git folder/objects/00/1ef10cbff8a9a485b09c7f0caf58cab2d053ce new file mode 100644 index 0000000..05ad4e9 Binary files /dev/null and b/gnu-efi/git folder/objects/00/1ef10cbff8a9a485b09c7f0caf58cab2d053ce differ diff --git a/gnu-efi/git folder/objects/02/75e18eb6a2b824eda21767a30657fd03d0cc07 b/gnu-efi/git folder/objects/02/75e18eb6a2b824eda21767a30657fd03d0cc07 new file mode 100644 index 0000000..dc21fc6 Binary files /dev/null and b/gnu-efi/git folder/objects/02/75e18eb6a2b824eda21767a30657fd03d0cc07 differ diff --git a/gnu-efi/git folder/objects/04/04787335eac0d264e37350b29a26d7034e554f b/gnu-efi/git folder/objects/04/04787335eac0d264e37350b29a26d7034e554f new file mode 100644 index 0000000..6786332 Binary files /dev/null and b/gnu-efi/git folder/objects/04/04787335eac0d264e37350b29a26d7034e554f differ diff --git a/gnu-efi/git folder/objects/05/6a33ce323d782379a7988a183e8c4074407ebe b/gnu-efi/git folder/objects/05/6a33ce323d782379a7988a183e8c4074407ebe new file mode 100644 index 0000000..25bfe56 Binary files /dev/null and b/gnu-efi/git folder/objects/05/6a33ce323d782379a7988a183e8c4074407ebe differ diff --git a/gnu-efi/git folder/objects/06/f24b3c49a6e1798a5115306ae1e97181d83ae0 b/gnu-efi/git folder/objects/06/f24b3c49a6e1798a5115306ae1e97181d83ae0 new file mode 100644 index 0000000..cb175fb Binary files /dev/null and b/gnu-efi/git folder/objects/06/f24b3c49a6e1798a5115306ae1e97181d83ae0 differ diff --git a/gnu-efi/git folder/objects/07/a56403494bfe4b3c7d3813d7c191b1135b71ca b/gnu-efi/git folder/objects/07/a56403494bfe4b3c7d3813d7c191b1135b71ca new file mode 100644 index 0000000..2e1aeb9 Binary files /dev/null and b/gnu-efi/git folder/objects/07/a56403494bfe4b3c7d3813d7c191b1135b71ca differ diff --git a/gnu-efi/git folder/objects/07/cb4c4aeb963c43735c40c6fd7dd2b1d60c0a69 b/gnu-efi/git folder/objects/07/cb4c4aeb963c43735c40c6fd7dd2b1d60c0a69 new file mode 100644 index 0000000..6e005e4 Binary files /dev/null and b/gnu-efi/git folder/objects/07/cb4c4aeb963c43735c40c6fd7dd2b1d60c0a69 differ diff --git a/gnu-efi/git folder/objects/09/ad7a429aa974a068457d43539f8aa520f0622f b/gnu-efi/git folder/objects/09/ad7a429aa974a068457d43539f8aa520f0622f new file mode 100644 index 0000000..af9e98a Binary files /dev/null and b/gnu-efi/git folder/objects/09/ad7a429aa974a068457d43539f8aa520f0622f differ diff --git a/gnu-efi/git folder/objects/0e/72223057bd8970c8d642cbbfaa055aacdd5464 b/gnu-efi/git folder/objects/0e/72223057bd8970c8d642cbbfaa055aacdd5464 new file mode 100644 index 0000000..fe74872 Binary files /dev/null and b/gnu-efi/git folder/objects/0e/72223057bd8970c8d642cbbfaa055aacdd5464 differ diff --git a/gnu-efi/git folder/objects/0e/cf403f47dc5b61e1c5a7b9f1e3cbd710082bff b/gnu-efi/git folder/objects/0e/cf403f47dc5b61e1c5a7b9f1e3cbd710082bff new file mode 100644 index 0000000..d2bf3f1 Binary files /dev/null and b/gnu-efi/git folder/objects/0e/cf403f47dc5b61e1c5a7b9f1e3cbd710082bff differ diff --git a/gnu-efi/git folder/objects/10/9c96a21e5eddcea7b9c4e88649a2ef8a1e3c16 b/gnu-efi/git folder/objects/10/9c96a21e5eddcea7b9c4e88649a2ef8a1e3c16 new file mode 100644 index 0000000..4f8bdb2 Binary files /dev/null and b/gnu-efi/git folder/objects/10/9c96a21e5eddcea7b9c4e88649a2ef8a1e3c16 differ diff --git a/gnu-efi/git folder/objects/12/074e91c992e89907d35d9885bbf321051a1a37 b/gnu-efi/git folder/objects/12/074e91c992e89907d35d9885bbf321051a1a37 new file mode 100644 index 0000000..10ff0f1 Binary files /dev/null and b/gnu-efi/git folder/objects/12/074e91c992e89907d35d9885bbf321051a1a37 differ diff --git a/gnu-efi/git folder/objects/16/0af87a0bf9d7dce4d6137976cfd3f0d6ec6138 b/gnu-efi/git folder/objects/16/0af87a0bf9d7dce4d6137976cfd3f0d6ec6138 new file mode 100644 index 0000000..b9f1da1 Binary files /dev/null and b/gnu-efi/git folder/objects/16/0af87a0bf9d7dce4d6137976cfd3f0d6ec6138 differ diff --git a/gnu-efi/git folder/objects/19/772a1bee19fdf71c1ef9fbe3e089813c6659ff b/gnu-efi/git folder/objects/19/772a1bee19fdf71c1ef9fbe3e089813c6659ff new file mode 100644 index 0000000..97a21fc Binary files /dev/null and b/gnu-efi/git folder/objects/19/772a1bee19fdf71c1ef9fbe3e089813c6659ff differ diff --git a/gnu-efi/git folder/objects/1a/52b164fd03876ddbded8fe121811d1639d51ea b/gnu-efi/git folder/objects/1a/52b164fd03876ddbded8fe121811d1639d51ea new file mode 100644 index 0000000..9cbced0 Binary files /dev/null and b/gnu-efi/git folder/objects/1a/52b164fd03876ddbded8fe121811d1639d51ea differ diff --git a/gnu-efi/git folder/objects/1f/86964791f20f6decb46e64aedeaa26b1b593e4 b/gnu-efi/git folder/objects/1f/86964791f20f6decb46e64aedeaa26b1b593e4 new file mode 100644 index 0000000..368427f Binary files /dev/null and b/gnu-efi/git folder/objects/1f/86964791f20f6decb46e64aedeaa26b1b593e4 differ diff --git a/gnu-efi/git folder/objects/24/112c682b1c111bbd808969b8d33909db1daa2a b/gnu-efi/git folder/objects/24/112c682b1c111bbd808969b8d33909db1daa2a new file mode 100644 index 0000000..552230a Binary files /dev/null and b/gnu-efi/git folder/objects/24/112c682b1c111bbd808969b8d33909db1daa2a differ diff --git a/gnu-efi/git folder/objects/28/04dbdc22a77738199c06513ce9092fb8d7e3dd b/gnu-efi/git folder/objects/28/04dbdc22a77738199c06513ce9092fb8d7e3dd new file mode 100644 index 0000000..961c9e8 Binary files /dev/null and b/gnu-efi/git folder/objects/28/04dbdc22a77738199c06513ce9092fb8d7e3dd differ diff --git a/gnu-efi/git folder/objects/29/9be4ef451b95c73bbd5fe2f4f782148a5931a7 b/gnu-efi/git folder/objects/29/9be4ef451b95c73bbd5fe2f4f782148a5931a7 new file mode 100644 index 0000000..397fd08 Binary files /dev/null and b/gnu-efi/git folder/objects/29/9be4ef451b95c73bbd5fe2f4f782148a5931a7 differ diff --git a/gnu-efi/git folder/objects/30/3fef9550667691cdce0e7f5408117e5752ee44 b/gnu-efi/git folder/objects/30/3fef9550667691cdce0e7f5408117e5752ee44 new file mode 100644 index 0000000..35054e4 --- /dev/null +++ b/gnu-efi/git folder/objects/30/3fef9550667691cdce0e7f5408117e5752ee44 @@ -0,0 +1,2 @@ +x+)JMU050c040031QpHKOOg̽(1SyF9K@F9Tobv^JjZbiNI1CMkk=]>o=adE9 =;'9^߳d3L[!8p{̸FU]zf qM.<7DJ>ESW6P+~kBbAA1T_SnD:)?$'?1%aW?K BC,I?Q_JrYDAf^2o 脻IL}MǺD.%!K_b!xKI/"[aaofP[g/:Fɖu \ No newline at end of file diff --git a/gnu-efi/git folder/objects/33/3efe9bbfaaf18a3d4e548708799022572a7f9c b/gnu-efi/git folder/objects/33/3efe9bbfaaf18a3d4e548708799022572a7f9c new file mode 100644 index 0000000..11819b0 Binary files /dev/null and b/gnu-efi/git folder/objects/33/3efe9bbfaaf18a3d4e548708799022572a7f9c differ diff --git a/gnu-efi/git folder/objects/33/943701231daf25251df0f6ff8cb263f7eef911 b/gnu-efi/git folder/objects/33/943701231daf25251df0f6ff8cb263f7eef911 new file mode 100644 index 0000000..ca9921b Binary files /dev/null and b/gnu-efi/git folder/objects/33/943701231daf25251df0f6ff8cb263f7eef911 differ diff --git a/gnu-efi/git folder/objects/36/4f6fc0b66c8e4a07362fc124a6735ab10fbac3 b/gnu-efi/git folder/objects/36/4f6fc0b66c8e4a07362fc124a6735ab10fbac3 new file mode 100644 index 0000000..7e384a8 Binary files /dev/null and b/gnu-efi/git folder/objects/36/4f6fc0b66c8e4a07362fc124a6735ab10fbac3 differ diff --git a/gnu-efi/git folder/objects/40/7d7e340f100a8eeb5eec18285ac984ed81cf3b b/gnu-efi/git folder/objects/40/7d7e340f100a8eeb5eec18285ac984ed81cf3b new file mode 100644 index 0000000..803b36d Binary files /dev/null and b/gnu-efi/git folder/objects/40/7d7e340f100a8eeb5eec18285ac984ed81cf3b differ diff --git a/gnu-efi/git folder/objects/40/f9319547ea62c1710201fa53aac0d74ab7538a b/gnu-efi/git folder/objects/40/f9319547ea62c1710201fa53aac0d74ab7538a new file mode 100644 index 0000000..51c64cf Binary files /dev/null and b/gnu-efi/git folder/objects/40/f9319547ea62c1710201fa53aac0d74ab7538a differ diff --git a/gnu-efi/git folder/objects/4d/137cf60c05c7dba0a466f8a64815315e155abe b/gnu-efi/git folder/objects/4d/137cf60c05c7dba0a466f8a64815315e155abe new file mode 100644 index 0000000..f31d012 Binary files /dev/null and b/gnu-efi/git folder/objects/4d/137cf60c05c7dba0a466f8a64815315e155abe differ diff --git a/gnu-efi/git folder/objects/4e/7691231ce2b4e58a5247468e446b4eb52536a9 b/gnu-efi/git folder/objects/4e/7691231ce2b4e58a5247468e446b4eb52536a9 new file mode 100644 index 0000000..0f31d92 Binary files /dev/null and b/gnu-efi/git folder/objects/4e/7691231ce2b4e58a5247468e446b4eb52536a9 differ diff --git a/gnu-efi/git folder/objects/4e/c6924c5486c6d1e0d059ac9955cb11aa861091 b/gnu-efi/git folder/objects/4e/c6924c5486c6d1e0d059ac9955cb11aa861091 new file mode 100644 index 0000000..dc932b8 Binary files /dev/null and b/gnu-efi/git folder/objects/4e/c6924c5486c6d1e0d059ac9955cb11aa861091 differ diff --git a/gnu-efi/git folder/objects/56/0d0deb0e05b7313d7fc08125d646c544588416 b/gnu-efi/git folder/objects/56/0d0deb0e05b7313d7fc08125d646c544588416 new file mode 100644 index 0000000..8fdcd33 Binary files /dev/null and b/gnu-efi/git folder/objects/56/0d0deb0e05b7313d7fc08125d646c544588416 differ diff --git a/gnu-efi/git folder/objects/56/6814e2c9154434ee8e2185da64b5ae9a3fc820 b/gnu-efi/git folder/objects/56/6814e2c9154434ee8e2185da64b5ae9a3fc820 new file mode 100644 index 0000000..d85618f Binary files /dev/null and b/gnu-efi/git folder/objects/56/6814e2c9154434ee8e2185da64b5ae9a3fc820 differ diff --git a/gnu-efi/git folder/objects/57/7f48d54c77efffcbda67c9b11e0b5b426826c9 b/gnu-efi/git folder/objects/57/7f48d54c77efffcbda67c9b11e0b5b426826c9 new file mode 100644 index 0000000..3ea5056 Binary files /dev/null and b/gnu-efi/git folder/objects/57/7f48d54c77efffcbda67c9b11e0b5b426826c9 differ diff --git a/gnu-efi/git folder/objects/58/59ed20aaf77054c8f569991fe30c4b62d685f1 b/gnu-efi/git folder/objects/58/59ed20aaf77054c8f569991fe30c4b62d685f1 new file mode 100644 index 0000000..14c0e92 --- /dev/null +++ b/gnu-efi/git folder/objects/58/59ed20aaf77054c8f569991fe30c4b62d685f1 @@ -0,0 +1,4 @@ +x+)JMU050c040031QpHKOOg̽(1SyF9K@F9Tobv^JjZbiNI1CMkk=]>o=adE9 =;'9^߳d3L[!8p{̸FU]zf qM.<7DJ>ESW6P+~kBbAA1T_SnD:)?$'?1%!5?S5\sf:=(bIэG0Rŗkݬ=Κ +2W};fp@'MJfo:֕N% p) aXj ě^Mz& + x3l.r2_@Ӊ1L| \ No newline at end of file diff --git a/gnu-efi/git folder/objects/5a/8f188df561eba46012050e272592b3e66adff6 b/gnu-efi/git folder/objects/5a/8f188df561eba46012050e272592b3e66adff6 new file mode 100644 index 0000000..4aa4161 Binary files /dev/null and b/gnu-efi/git folder/objects/5a/8f188df561eba46012050e272592b3e66adff6 differ diff --git a/gnu-efi/git folder/objects/5d/1bb68e938d6a131da6e458439a42162e132aeb b/gnu-efi/git folder/objects/5d/1bb68e938d6a131da6e458439a42162e132aeb new file mode 100644 index 0000000..15cf1e6 Binary files /dev/null and b/gnu-efi/git folder/objects/5d/1bb68e938d6a131da6e458439a42162e132aeb differ diff --git a/gnu-efi/git folder/objects/61/34931cfe441e51d86b3dc42ef743e9510ca0fa b/gnu-efi/git folder/objects/61/34931cfe441e51d86b3dc42ef743e9510ca0fa new file mode 100644 index 0000000..9c1f8e2 Binary files /dev/null and b/gnu-efi/git folder/objects/61/34931cfe441e51d86b3dc42ef743e9510ca0fa differ diff --git a/gnu-efi/git folder/objects/65/0cee40d50c82f60c577fa712d9d67efaae5dd6 b/gnu-efi/git folder/objects/65/0cee40d50c82f60c577fa712d9d67efaae5dd6 new file mode 100644 index 0000000..c4636d5 Binary files /dev/null and b/gnu-efi/git folder/objects/65/0cee40d50c82f60c577fa712d9d67efaae5dd6 differ diff --git a/gnu-efi/git folder/objects/65/6f5ecdecc0952845619f0a156941edc26ebf4b b/gnu-efi/git folder/objects/65/6f5ecdecc0952845619f0a156941edc26ebf4b new file mode 100644 index 0000000..0d6cda6 Binary files /dev/null and b/gnu-efi/git folder/objects/65/6f5ecdecc0952845619f0a156941edc26ebf4b differ diff --git a/gnu-efi/git folder/objects/6c/20e90a6ac98425a51db426213262e3747c186e b/gnu-efi/git folder/objects/6c/20e90a6ac98425a51db426213262e3747c186e new file mode 100644 index 0000000..769c3c0 Binary files /dev/null and b/gnu-efi/git folder/objects/6c/20e90a6ac98425a51db426213262e3747c186e differ diff --git a/gnu-efi/git folder/objects/6c/7816cadc8452b3b9a4952309e22cfa2bb2e9d9 b/gnu-efi/git folder/objects/6c/7816cadc8452b3b9a4952309e22cfa2bb2e9d9 new file mode 100644 index 0000000..10a7de3 Binary files /dev/null and b/gnu-efi/git folder/objects/6c/7816cadc8452b3b9a4952309e22cfa2bb2e9d9 differ diff --git a/gnu-efi/git folder/objects/6e/a6be4d062a55e874d22ebe8831f6bc345378e6 b/gnu-efi/git folder/objects/6e/a6be4d062a55e874d22ebe8831f6bc345378e6 new file mode 100644 index 0000000..c233aa7 Binary files /dev/null and b/gnu-efi/git folder/objects/6e/a6be4d062a55e874d22ebe8831f6bc345378e6 differ diff --git a/gnu-efi/git folder/objects/6e/c48dfd0eb62e7d0ca773f3b11a5b6d26b4dd3c b/gnu-efi/git folder/objects/6e/c48dfd0eb62e7d0ca773f3b11a5b6d26b4dd3c new file mode 100644 index 0000000..26552c9 Binary files /dev/null and b/gnu-efi/git folder/objects/6e/c48dfd0eb62e7d0ca773f3b11a5b6d26b4dd3c differ diff --git a/gnu-efi/git folder/objects/70/33c49e0bc873845d30dcb184fde631398904ad b/gnu-efi/git folder/objects/70/33c49e0bc873845d30dcb184fde631398904ad new file mode 100644 index 0000000..5528563 Binary files /dev/null and b/gnu-efi/git folder/objects/70/33c49e0bc873845d30dcb184fde631398904ad differ diff --git a/gnu-efi/git folder/objects/71/be5b9347fb34e8ab0030a0344005d5c9bc55d7 b/gnu-efi/git folder/objects/71/be5b9347fb34e8ab0030a0344005d5c9bc55d7 new file mode 100644 index 0000000..d7a2e92 Binary files /dev/null and b/gnu-efi/git folder/objects/71/be5b9347fb34e8ab0030a0344005d5c9bc55d7 differ diff --git a/gnu-efi/git folder/objects/76/da8603cc06ab15c5e32773ea77ccdafc4674b7 b/gnu-efi/git folder/objects/76/da8603cc06ab15c5e32773ea77ccdafc4674b7 new file mode 100644 index 0000000..72cd1ce Binary files /dev/null and b/gnu-efi/git folder/objects/76/da8603cc06ab15c5e32773ea77ccdafc4674b7 differ diff --git a/gnu-efi/git folder/objects/7c/55e96b586f4bf26305f6815422d99ed86cf532 b/gnu-efi/git folder/objects/7c/55e96b586f4bf26305f6815422d99ed86cf532 new file mode 100644 index 0000000..36f2608 Binary files /dev/null and b/gnu-efi/git folder/objects/7c/55e96b586f4bf26305f6815422d99ed86cf532 differ diff --git a/gnu-efi/git folder/objects/80/52e8f5fbf4ad85d119ae4381829227c3155b30 b/gnu-efi/git folder/objects/80/52e8f5fbf4ad85d119ae4381829227c3155b30 new file mode 100644 index 0000000..97b31e6 Binary files /dev/null and b/gnu-efi/git folder/objects/80/52e8f5fbf4ad85d119ae4381829227c3155b30 differ diff --git a/gnu-efi/git folder/objects/80/6f1c18463baac7db8f7f2807396fc7ddb135c3 b/gnu-efi/git folder/objects/80/6f1c18463baac7db8f7f2807396fc7ddb135c3 new file mode 100644 index 0000000..84b8576 Binary files /dev/null and b/gnu-efi/git folder/objects/80/6f1c18463baac7db8f7f2807396fc7ddb135c3 differ diff --git a/gnu-efi/git folder/objects/83/16ea765df866d36e9c029d1963cd0116a388ad b/gnu-efi/git folder/objects/83/16ea765df866d36e9c029d1963cd0116a388ad new file mode 100644 index 0000000..82808b2 Binary files /dev/null and b/gnu-efi/git folder/objects/83/16ea765df866d36e9c029d1963cd0116a388ad differ diff --git a/gnu-efi/git folder/objects/83/2454741671fa9cb75f83c0aee15dfd9fc81e95 b/gnu-efi/git folder/objects/83/2454741671fa9cb75f83c0aee15dfd9fc81e95 new file mode 100644 index 0000000..e37ee1c Binary files /dev/null and b/gnu-efi/git folder/objects/83/2454741671fa9cb75f83c0aee15dfd9fc81e95 differ diff --git a/gnu-efi/git folder/objects/89/40bb1f57867fe40d18bdbbcc3637ea085a49eb b/gnu-efi/git folder/objects/89/40bb1f57867fe40d18bdbbcc3637ea085a49eb new file mode 100644 index 0000000..e3c8202 Binary files /dev/null and b/gnu-efi/git folder/objects/89/40bb1f57867fe40d18bdbbcc3637ea085a49eb differ diff --git a/gnu-efi/git folder/objects/90/1e42ea106bbae49e94779bf42a09c821f258a0 b/gnu-efi/git folder/objects/90/1e42ea106bbae49e94779bf42a09c821f258a0 new file mode 100644 index 0000000..a21c444 Binary files /dev/null and b/gnu-efi/git folder/objects/90/1e42ea106bbae49e94779bf42a09c821f258a0 differ diff --git a/gnu-efi/git folder/objects/92/138354ba0f77a7a7d857b2a7686ba9e9f1d63e b/gnu-efi/git folder/objects/92/138354ba0f77a7a7d857b2a7686ba9e9f1d63e new file mode 100644 index 0000000..7ce7b8c Binary files /dev/null and b/gnu-efi/git folder/objects/92/138354ba0f77a7a7d857b2a7686ba9e9f1d63e differ diff --git a/gnu-efi/git folder/objects/92/adfbc1fb30b4a4ec85960fbf19e11f6877dcdf b/gnu-efi/git folder/objects/92/adfbc1fb30b4a4ec85960fbf19e11f6877dcdf new file mode 100644 index 0000000..ca44059 Binary files /dev/null and b/gnu-efi/git folder/objects/92/adfbc1fb30b4a4ec85960fbf19e11f6877dcdf differ diff --git a/gnu-efi/git folder/objects/97/2d2c8bc3086b65f45bcff9684fbda6ab73cd47 b/gnu-efi/git folder/objects/97/2d2c8bc3086b65f45bcff9684fbda6ab73cd47 new file mode 100644 index 0000000..26c1d7c Binary files /dev/null and b/gnu-efi/git folder/objects/97/2d2c8bc3086b65f45bcff9684fbda6ab73cd47 differ diff --git a/gnu-efi/git folder/objects/99/5adea53d4907ef1b4ff910f4991236ab8303f0 b/gnu-efi/git folder/objects/99/5adea53d4907ef1b4ff910f4991236ab8303f0 new file mode 100644 index 0000000..fba9385 Binary files /dev/null and b/gnu-efi/git folder/objects/99/5adea53d4907ef1b4ff910f4991236ab8303f0 differ diff --git a/gnu-efi/git folder/objects/9b/a1d9ecc090376a3e9315d2cb4d634c1a7149ac b/gnu-efi/git folder/objects/9b/a1d9ecc090376a3e9315d2cb4d634c1a7149ac new file mode 100644 index 0000000..2cd5e77 Binary files /dev/null and b/gnu-efi/git folder/objects/9b/a1d9ecc090376a3e9315d2cb4d634c1a7149ac differ diff --git a/gnu-efi/git folder/objects/9b/bcb6607cd36ecdbc1343699ca2ee1e9010aa0c b/gnu-efi/git folder/objects/9b/bcb6607cd36ecdbc1343699ca2ee1e9010aa0c new file mode 100644 index 0000000..f84e66e Binary files /dev/null and b/gnu-efi/git folder/objects/9b/bcb6607cd36ecdbc1343699ca2ee1e9010aa0c differ diff --git a/gnu-efi/git folder/objects/9c/39a588b9233d8e8261555ac134709319461551 b/gnu-efi/git folder/objects/9c/39a588b9233d8e8261555ac134709319461551 new file mode 100644 index 0000000..414a517 Binary files /dev/null and b/gnu-efi/git folder/objects/9c/39a588b9233d8e8261555ac134709319461551 differ diff --git a/gnu-efi/git folder/objects/9c/416eb0ff71a1b857d38adf70d9724960e5b657 b/gnu-efi/git folder/objects/9c/416eb0ff71a1b857d38adf70d9724960e5b657 new file mode 100644 index 0000000..3984541 --- /dev/null +++ b/gnu-efi/git folder/objects/9c/416eb0ff71a1b857d38adf70d9724960e5b657 @@ -0,0 +1 @@ +x+)JMU042c040031QH.*1MMԭ073gXw3f Xu +# Contributed by Stephane Eranian +# +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following +# disclaimer in the documentation and/or other materials +# provided with the distribution. +# * Neither the name of Hewlett-Packard Co. nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND +# CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +# INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS +# BE LIABLE FOR ANYDIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, +# OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR +# TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF +# THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. +# + +SRCDIR = . + +VPATH = $(SRCDIR) + +include $(SRCDIR)/../Make.defaults + +TOPDIR = $(SRCDIR)/.. + +CDIR=$(TOPDIR)/.. +FILES = reloc_$(ARCH) + +OBJS = $(FILES:%=%.o) + +# on aarch64, avoid jump tables before all relocations have been processed +reloc_aarch64.o: CFLAGS += -fno-jump-tables + +TARGETS = crt0-efi-$(ARCH).o libgnuefi.a + +all: $(TARGETS) + +libgnuefi.a: $(OBJS) + $(AR) $(ARFLAGS) $@ $^ + + +clean: + rm -f $(TARGETS) *~ *.o $(OBJS) + +install: + mkdir -p $(INSTALLROOT)$(LIBDIR) + $(INSTALL) -m 644 $(TARGETS) $(INSTALLROOT)$(LIBDIR) +ifneq (,$(findstring FreeBSD,$(OS))) + ifeq ($(ARCH),x86_64) + $(INSTALL) -m 644 $(SRCDIR)/elf_$(ARCH)_fbsd_efi.lds $(INSTALLROOT)$(LIBDIR) + else + $(INSTALL) -m 644 $(SRCDIR)/elf_$(ARCH)_efi.lds $(INSTALLROOT)$(LIBDIR) + endif +else + $(INSTALL) -m 644 $(SRCDIR)/elf_$(ARCH)_efi.lds $(INSTALLROOT)$(LIBDIR) +endif + +include $(SRCDIR)/../Make.rules diff --git a/gnu-efi/gnuefi/crt0-efi-aarch64.S b/gnu-efi/gnuefi/crt0-efi-aarch64.S new file mode 100644 index 0000000..c300d89 --- /dev/null +++ b/gnu-efi/gnuefi/crt0-efi-aarch64.S @@ -0,0 +1,130 @@ +/* + * crt0-efi-aarch64.S - PE/COFF header for AArch64 EFI applications + * + * Copright (C) 2014 Linaro Ltd. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice and this list of conditions, without modification. + * 2. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * Alternatively, this software may be distributed 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. + */ + + .section .text.head + + /* + * Magic "MZ" signature for PE/COFF + */ + .globl ImageBase +ImageBase: + .ascii "MZ" + .skip 58 // 'MZ' + pad + offset == 64 + .long pe_header - ImageBase // Offset to the PE header. +pe_header: + .ascii "PE" + .short 0 +coff_header: + .short 0xaa64 // AArch64 + .short 2 // nr_sections + .long 0 // TimeDateStamp + .long 0 // PointerToSymbolTable + .long 1 // NumberOfSymbols + .short section_table - optional_header // SizeOfOptionalHeader + .short 0x206 // Characteristics. + // IMAGE_FILE_DEBUG_STRIPPED | + // IMAGE_FILE_EXECUTABLE_IMAGE | + // IMAGE_FILE_LINE_NUMS_STRIPPED +optional_header: + .short 0x20b // PE32+ format + .byte 0x02 // MajorLinkerVersion + .byte 0x14 // MinorLinkerVersion + .long _data - _start // SizeOfCode + .long _data_size // SizeOfInitializedData + .long 0 // SizeOfUninitializedData + .long _start - ImageBase // AddressOfEntryPoint + .long _start - ImageBase // BaseOfCode + +extra_header_fields: + .quad 0 // ImageBase + .long 0x1000 // SectionAlignment + .long 0x200 // FileAlignment + .short 0 // MajorOperatingSystemVersion + .short 0 // MinorOperatingSystemVersion + .short 0 // MajorImageVersion + .short 0 // MinorImageVersion + .short 0 // MajorSubsystemVersion + .short 0 // MinorSubsystemVersion + .long 0 // Win32VersionValue + + .long _edata - ImageBase // SizeOfImage + + // Everything before the kernel image is considered part of the header + .long _start - ImageBase // SizeOfHeaders + .long 0 // CheckSum + .short EFI_SUBSYSTEM // Subsystem + .short 0 // DllCharacteristics + .quad 0 // SizeOfStackReserve + .quad 0 // SizeOfStackCommit + .quad 0 // SizeOfHeapReserve + .quad 0 // SizeOfHeapCommit + .long 0 // LoaderFlags + .long 0x6 // NumberOfRvaAndSizes + + .quad 0 // ExportTable + .quad 0 // ImportTable + .quad 0 // ResourceTable + .quad 0 // ExceptionTable + .quad 0 // CertificationTable + .quad 0 // BaseRelocationTable + + // Section table +section_table: + .ascii ".text\0\0\0" + .long _data - _start // VirtualSize + .long _start - ImageBase // VirtualAddress + .long _data - _start // SizeOfRawData + .long _start - ImageBase // PointerToRawData + + .long 0 // PointerToRelocations (0 for executables) + .long 0 // PointerToLineNumbers (0 for executables) + .short 0 // NumberOfRelocations (0 for executables) + .short 0 // NumberOfLineNumbers (0 for executables) + .long 0x60000020 // Characteristics (section flags) + + .ascii ".data\0\0\0" + .long _data_size // VirtualSize + .long _data - ImageBase // VirtualAddress + .long _data_size // SizeOfRawData + .long _data - ImageBase // PointerToRawData + + .long 0 // PointerToRelocations (0 for executables) + .long 0 // PointerToLineNumbers (0 for executables) + .short 0 // NumberOfRelocations (0 for executables) + .short 0 // NumberOfLineNumbers (0 for executables) + .long 0xc0000040 // Characteristics (section flags) + + .align 12 +_start: + stp x29, x30, [sp, #-32]! + mov x29, sp + + stp x0, x1, [sp, #16] + mov x2, x0 + mov x3, x1 + adr x0, ImageBase + adrp x1, _DYNAMIC + add x1, x1, #:lo12:_DYNAMIC + bl _relocate + cbnz x0, 0f + + ldp x0, x1, [sp, #16] + bl efi_main + +0: ldp x29, x30, [sp], #32 + ret diff --git a/gnu-efi/gnuefi/crt0-efi-arm.S b/gnu-efi/gnuefi/crt0-efi-arm.S new file mode 100644 index 0000000..c5bb6d4 --- /dev/null +++ b/gnu-efi/gnuefi/crt0-efi-arm.S @@ -0,0 +1,145 @@ +/* + * crt0-efi-arm.S - PE/COFF header for ARM EFI applications + * + * Copright (C) 2014 Linaro Ltd. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice and this list of conditions, without modification. + * 2. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * Alternatively, this software may be distributed 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. + */ + + .section .text.head + + /* + * Magic "MZ" signature for PE/COFF + */ + .globl ImageBase +ImageBase: + .ascii "MZ" + .skip 58 // 'MZ' + pad + offset == 64 + .long pe_header - ImageBase // Offset to the PE header. +pe_header: + .ascii "PE" + .short 0 +coff_header: + .short 0x1c2 // Mixed ARM/Thumb + .short 2 // nr_sections + .long 0 // TimeDateStamp + .long 0 // PointerToSymbolTable + .long 1 // NumberOfSymbols + .short section_table - optional_header // SizeOfOptionalHeader + .short 0x306 // Characteristics. + // IMAGE_FILE_32BIT_MACHINE | + // IMAGE_FILE_DEBUG_STRIPPED | + // IMAGE_FILE_EXECUTABLE_IMAGE | + // IMAGE_FILE_LINE_NUMS_STRIPPED +optional_header: + .short 0x10b // PE32+ format + .byte 0x02 // MajorLinkerVersion + .byte 0x14 // MinorLinkerVersion + .long _edata - _start // SizeOfCode + .long 0 // SizeOfInitializedData + .long 0 // SizeOfUninitializedData + .long _start - ImageBase // AddressOfEntryPoint + .long _start - ImageBase // BaseOfCode + .long 0 // BaseOfData + +extra_header_fields: + .long 0 // ImageBase + .long 0x20 // SectionAlignment + .long 0x8 // FileAlignment + .short 0 // MajorOperatingSystemVersion + .short 0 // MinorOperatingSystemVersion + .short 0 // MajorImageVersion + .short 0 // MinorImageVersion + .short 0 // MajorSubsystemVersion + .short 0 // MinorSubsystemVersion + .long 0 // Win32VersionValue + + .long _edata - ImageBase // SizeOfImage + + // Everything before the kernel image is considered part of the header + .long _start - ImageBase // SizeOfHeaders + .long 0 // CheckSum + .short EFI_SUBSYSTEM // Subsystem + .short 0 // DllCharacteristics + .long 0 // SizeOfStackReserve + .long 0 // SizeOfStackCommit + .long 0 // SizeOfHeapReserve + .long 0 // SizeOfHeapCommit + .long 0 // LoaderFlags + .long 0x6 // NumberOfRvaAndSizes + + .quad 0 // ExportTable + .quad 0 // ImportTable + .quad 0 // ResourceTable + .quad 0 // ExceptionTable + .quad 0 // CertificationTable + .quad 0 // BaseRelocationTable + + // Section table +section_table: + + /* + * The EFI application loader requires a relocation section + * because EFI applications must be relocatable. This is a + * dummy section as far as we are concerned. + */ + .ascii ".reloc" + .byte 0 + .byte 0 // end of 0 padding of section name + .long 0 + .long 0 + .long 0 // SizeOfRawData + .long 0 // PointerToRawData + .long 0 // PointerToRelocations + .long 0 // PointerToLineNumbers + .short 0 // NumberOfRelocations + .short 0 // NumberOfLineNumbers + .long 0x42100040 // Characteristics (section flags) + + + .ascii ".text" + .byte 0 + .byte 0 + .byte 0 // end of 0 padding of section name + .long _edata - _start // VirtualSize + .long _start - ImageBase // VirtualAddress + .long _edata - _start // SizeOfRawData + .long _start - ImageBase // PointerToRawData + + .long 0 // PointerToRelocations (0 for executables) + .long 0 // PointerToLineNumbers (0 for executables) + .short 0 // NumberOfRelocations (0 for executables) + .short 0 // NumberOfLineNumbers (0 for executables) + .long 0xe0500020 // Characteristics (section flags) + +_start: + stmfd sp!, {r0-r2, lr} + + mov r2, r0 + mov r3, r1 + adr r1, .L_DYNAMIC + ldr r0, [r1] + add r1, r0, r1 + adr r0, ImageBase + bl _relocate + teq r0, #0 + bne 0f + + ldmfd sp, {r0-r1} + bl efi_main + +0: add sp, sp, #12 + ldr pc, [sp], #4 + +.L_DYNAMIC: + .word _DYNAMIC - . diff --git a/gnu-efi/gnuefi/crt0-efi-ia32.S b/gnu-efi/gnuefi/crt0-efi-ia32.S new file mode 100644 index 0000000..f9d5191 --- /dev/null +++ b/gnu-efi/gnuefi/crt0-efi-ia32.S @@ -0,0 +1,76 @@ +/* crt0-efi-ia32.S - x86 EFI startup code. + Copyright (C) 1999 Hewlett-Packard Co. + Contributed by David Mosberger . + + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials + provided with the distribution. + * Neither the name of Hewlett-Packard Co. nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + BE LIABLE FOR ANYDIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF + THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. +*/ + + .text + .align 4 + + .globl _start +_start: + pushl %ebp + movl %esp,%ebp + + pushl 12(%ebp) # copy "image" argument + pushl 8(%ebp) # copy "systab" argument + + call 0f +0: popl %eax + movl %eax,%ebx + + addl $ImageBase-0b,%eax # %eax = ldbase + addl $_DYNAMIC-0b,%ebx # %ebx = _DYNAMIC + + pushl %ebx # pass _DYNAMIC as second argument + pushl %eax # pass ldbase as first argument + call _relocate + popl %ebx + popl %ebx + testl %eax,%eax + jne .exit + + call efi_main # call app with "image" and "systab" argument + +.exit: leave + ret + + // hand-craft a dummy .reloc section so EFI knows it's a relocatable executable: + + .data +dummy: .long 0 + +#define IMAGE_REL_ABSOLUTE 0 + .section .reloc + .long dummy // Page RVA + .long 10 // Block Size (2*4+2) + .word (IMAGE_REL_ABSOLUTE<<12) + 0 // reloc for dummy diff --git a/gnu-efi/gnuefi/crt0-efi-ia64.S b/gnu-efi/gnuefi/crt0-efi-ia64.S new file mode 100644 index 0000000..40c3c83 --- /dev/null +++ b/gnu-efi/gnuefi/crt0-efi-ia64.S @@ -0,0 +1,87 @@ +/* crt0-efi-ia64.S - IA-64 EFI startup code. + Copyright (C) 1999 Hewlett-Packard Co. + Contributed by David Mosberger . + + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials + provided with the distribution. + * Neither the name of Hewlett-Packard Co. nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + BE LIABLE FOR ANYDIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF + THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. +*/ + .text + .psr abi64 + .psr lsb + .lsb + + .proc _start +_start: + alloc loc0=ar.pfs,2,2,2,0 + mov loc1=rp + movl out0=@gprel(ImageBase) // out0 <- ImageBase (ldbase) + ;; + add out0=out0,gp + movl out1=@gprel(_DYNAMIC) // out1 <- _DYNAMIC + ;; // avoid WAW on CFM + add out1=out1,gp + br.call.sptk.few rp=_relocate +.Lret0: + cmp.ne p6,p0=r0,r8 // r8 == EFI_SUCCESS? +(p6) br.cond.sptk.few .exit // no -> + +.Lret1: + + mov out0=in0 // image handle + mov out1=in1 // systab + br.call.sptk.few rp=efi_main +.Lret2: +.exit: + mov ar.pfs=loc0 + mov rp=loc1 + ;; + br.ret.sptk.few rp + + .endp _start + + + // PE32+ wants a PLABEL, not the code address of the entry point: + + .align 16 + .global _start_plabel + .section .plabel, "a" +_start_plabel: + data8 _start + data8 __gp + + // hand-craft a .reloc section for the plabel: + +#define IMAGE_REL_BASED_DIR64 10 + + .section .reloc, "a" + data4 _start_plabel // Page RVA + data4 12 // Block Size (2*4+2*2) + data2 (IMAGE_REL_BASED_DIR64<<12) + 0 // reloc for plabel's entry point + data2 (IMAGE_REL_BASED_DIR64<<12) + 8 // reloc for plabel's global pointer diff --git a/gnu-efi/gnuefi/crt0-efi-mips64el.S b/gnu-efi/gnuefi/crt0-efi-mips64el.S new file mode 100644 index 0000000..6a62aca --- /dev/null +++ b/gnu-efi/gnuefi/crt0-efi-mips64el.S @@ -0,0 +1,188 @@ +/* + * crt0-efi-mips64el.S - PE/COFF header for MIPS64 EFI applications + * + * Copright (C) 2014 Linaro Ltd. + * Copright (C) 2017 Heiher + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice and this list of conditions, without modification. + * 2. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * Alternatively, this software may be distributed 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. + */ + + .section .text.head + + /* + * Magic "MZ" signature for PE/COFF + */ + .globl ImageBase +ImageBase: + .ascii "MZ" + .skip 58 // 'MZ' + pad + offset == 64 + .long pe_header - ImageBase // Offset to the PE header. +pe_header: + .ascii "PE" + .short 0 +coff_header: + .short 0x166 // MIPS little endian + .short 2 // nr_sections + .long 0 // TimeDateStamp + .long 0 // PointerToSymbolTable + .long 1 // NumberOfSymbols + .short section_table - optional_header // SizeOfOptionalHeader + .short 0x206 // Characteristics. + // IMAGE_FILE_DEBUG_STRIPPED | + // IMAGE_FILE_EXECUTABLE_IMAGE | + // IMAGE_FILE_LINE_NUMS_STRIPPED +optional_header: + .short 0x20b // PE32+ format + .byte 0x02 // MajorLinkerVersion + .byte 0x14 // MinorLinkerVersion + .long _edata - _start // SizeOfCode + .long 0 // SizeOfInitializedData + .long 0 // SizeOfUninitializedData + .long _start - ImageBase // AddressOfEntryPoint + .long _start - ImageBase // BaseOfCode + +extra_header_fields: + .quad 0 // ImageBase + .long 0x20 // SectionAlignment + .long 0x8 // FileAlignment + .short 0 // MajorOperatingSystemVersion + .short 0 // MinorOperatingSystemVersion + .short 0 // MajorImageVersion + .short 0 // MinorImageVersion + .short 0 // MajorSubsystemVersion + .short 0 // MinorSubsystemVersion + .long 0 // Win32VersionValue + + .long _edata - ImageBase // SizeOfImage + + // Everything before the kernel image is considered part of the header + .long _start - ImageBase // SizeOfHeaders + .long 0 // CheckSum + .short EFI_SUBSYSTEM // Subsystem + .short 0 // DllCharacteristics + .quad 0 // SizeOfStackReserve + .quad 0 // SizeOfStackCommit + .quad 0 // SizeOfHeapReserve + .quad 0 // SizeOfHeapCommit + .long 0 // LoaderFlags + .long 0x6 // NumberOfRvaAndSizes + + .quad 0 // ExportTable + .quad 0 // ImportTable + .quad 0 // ResourceTable + .quad 0 // ExceptionTable + .quad 0 // CertificationTable + .quad 0 // BaseRelocationTable + + // Section table +section_table: + + /* + * The EFI application loader requires a relocation section + * because EFI applications must be relocatable. This is a + * dummy section as far as we are concerned. + */ + .ascii ".reloc" + .byte 0 + .byte 0 // end of 0 padding of section name + .long 0 + .long 0 + .long 0 // SizeOfRawData + .long 0 // PointerToRawData + .long 0 // PointerToRelocations + .long 0 // PointerToLineNumbers + .short 0 // NumberOfRelocations + .short 0 // NumberOfLineNumbers + .long 0x42100040 // Characteristics (section flags) + + + .ascii ".text" + .byte 0 + .byte 0 + .byte 0 // end of 0 padding of section name + .long _edata - _start // VirtualSize + .long _start - ImageBase // VirtualAddress + .long _edata - _start // SizeOfRawData + .long _start - ImageBase // PointerToRawData + + .long 0 // PointerToRelocations (0 for executables) + .long 0 // PointerToLineNumbers (0 for executables) + .short 0 // NumberOfRelocations (0 for executables) + .short 0 // NumberOfLineNumbers (0 for executables) + .long 0xe0500020 // Characteristics (section flags) + + .set push + .set noreorder + .align 4 + + .globl _start + .ent _start + .type _start, @function +_start: + daddiu $sp, -32 + sd $ra, ($sp) + + // Get pc & gp + .align 3 + bal 1f + sd $gp, 8($sp) +_pc: + .dword _gp + .dword _DYNAMIC + .dword _relocate +1: + // pc in ra + ld $gp, ($ra) + dli $t0, _pc + dsubu $gp, $t0 + daddu $gp, $ra + + sd $a0, 16($sp) + sd $a1, 24($sp) + + // a2: ImageHandle + move $a2, $a0 + // a3: SystemTable + move $a3, $a1 + // a0: ImageBase + dli $t1, ImageBase - _pc + daddu $a0, $ra, $t1 + // a1: DynamicSection + ld $t1, 8($ra) + dsubu $t1, $t0 + daddu $a1, $ra, $t1 + // call _relocate + ld $t1, 16($ra) + dsubu $t1, $t0 + daddu $t9, $ra, $t1 + jalr $t9 + nop + bnez $v0, 1b + nop + + // a0: ImageHandle + ld $a0, 16($sp) + // call efi_main + dla $t9, efi_main + jalr $t9 + // a1: SystemTable + ld $a1, 24($sp) + +1: + ld $gp, 8($sp) + ld $ra, ($sp) + jr $ra + daddiu $sp, 32 + .end _start + + .set pop diff --git a/gnu-efi/gnuefi/crt0-efi-x86_64.S b/gnu-efi/gnuefi/crt0-efi-x86_64.S new file mode 100644 index 0000000..6839150 --- /dev/null +++ b/gnu-efi/gnuefi/crt0-efi-x86_64.S @@ -0,0 +1,76 @@ +/* crt0-efi-x86_64.S - x86_64 EFI startup code. + Copyright (C) 1999 Hewlett-Packard Co. + Contributed by David Mosberger . + Copyright (C) 2005 Intel Co. + Contributed by Fenghua Yu . + + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials + provided with the distribution. + * Neither the name of Hewlett-Packard Co. nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + BE LIABLE FOR ANYDIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF + THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. +*/ + .text + .align 4 + + .globl _start +_start: + subq $8, %rsp + pushq %rcx + pushq %rdx + +0: + lea ImageBase(%rip), %rdi + lea _DYNAMIC(%rip), %rsi + + popq %rcx + popq %rdx + pushq %rcx + pushq %rdx + call _relocate + + popq %rdi + popq %rsi + + call efi_main + addq $8, %rsp + +.exit: + ret + + // hand-craft a dummy .reloc section so EFI knows it's a relocatable executable: + + .data +dummy: .long 0 + +#define IMAGE_REL_ABSOLUTE 0 + .section .reloc, "a" +label1: + .long dummy-label1 // Page RVA + .long 10 // Block Size (2*4+2) + .word (IMAGE_REL_ABSOLUTE<<12) + 0 // reloc for dummy + diff --git a/gnu-efi/gnuefi/elf_aarch64_efi.lds b/gnu-efi/gnuefi/elf_aarch64_efi.lds new file mode 100644 index 0000000..836d982 --- /dev/null +++ b/gnu-efi/gnuefi/elf_aarch64_efi.lds @@ -0,0 +1,63 @@ +OUTPUT_FORMAT("elf64-littleaarch64", "elf64-littleaarch64", "elf64-littleaarch64") +OUTPUT_ARCH(aarch64) +ENTRY(_start) +SECTIONS +{ + .text 0x0 : { + _text = .; + *(.text.head) + *(.text) + *(.text.*) + *(.gnu.linkonce.t.*) + *(.srodata) + *(.rodata*) + . = ALIGN(16); + } + _etext = .; + _text_size = . - _text; + .dynamic : { *(.dynamic) } + .data : ALIGN(4096) + { + _data = .; + *(.sdata) + *(.data) + *(.data1) + *(.data.*) + *(.got.plt) + *(.got) + + /* the EFI loader doesn't seem to like a .bss section, so we stick + it all into .data: */ + . = ALIGN(16); + _bss = .; + *(.sbss) + *(.scommon) + *(.dynbss) + *(.bss) + *(COMMON) + . = ALIGN(16); + _bss_end = .; + } + + .rela.dyn : { *(.rela.dyn) } + .rela.plt : { *(.rela.plt) } + .rela.got : { *(.rela.got) } + .rela.data : { *(.rela.data) *(.rela.data*) } + . = ALIGN(512); + _edata = .; + _data_size = . - _data; + + . = ALIGN(4096); + .dynsym : { *(.dynsym) } + . = ALIGN(4096); + .dynstr : { *(.dynstr) } + . = ALIGN(4096); + .note.gnu.build-id : { *(.note.gnu.build-id) } + /DISCARD/ : + { + *(.rel.reloc) + *(.eh_frame) + *(.note.GNU-stack) + } + .comment 0 : { *(.comment) } +} diff --git a/gnu-efi/gnuefi/elf_arm_efi.lds b/gnu-efi/gnuefi/elf_arm_efi.lds new file mode 100644 index 0000000..665bbdb --- /dev/null +++ b/gnu-efi/gnuefi/elf_arm_efi.lds @@ -0,0 +1,63 @@ +OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") +OUTPUT_ARCH(arm) +ENTRY(_start) +SECTIONS +{ + .text 0x0 : { + _text = .; + *(.text.head) + *(.text) + *(.text.*) + *(.gnu.linkonce.t.*) + *(.srodata) + *(.rodata*) + . = ALIGN(16); + } + _etext = .; + _text_size = . - _text; + .dynamic : { *(.dynamic) } + .data : + { + _data = .; + *(.sdata) + *(.data) + *(.data1) + *(.data.*) + *(.got.plt) + *(.got) + + /* the EFI loader doesn't seem to like a .bss section, so we stick + it all into .data: */ + . = ALIGN(16); + _bss = .; + *(.sbss) + *(.scommon) + *(.dynbss) + *(.bss) + *(.bss.*) + *(COMMON) + . = ALIGN(16); + _bss_end = .; + } + + .rel.dyn : { *(.rel.dyn) } + .rel.plt : { *(.rel.plt) } + .rel.got : { *(.rel.got) } + .rel.data : { *(.rel.data) *(.rel.data*) } + _edata = .; + _data_size = . - _etext; + + . = ALIGN(4096); + .dynsym : { *(.dynsym) } + . = ALIGN(4096); + .dynstr : { *(.dynstr) } + . = ALIGN(4096); + .note.gnu.build-id : { *(.note.gnu.build-id) } + /DISCARD/ : + { + *(.rel.reloc) + *(.eh_frame) + *(.note.GNU-stack) + } + .comment 0 : { *(.comment) } +} diff --git a/gnu-efi/gnuefi/elf_ia32_efi.lds b/gnu-efi/gnuefi/elf_ia32_efi.lds new file mode 100644 index 0000000..f27fe5f --- /dev/null +++ b/gnu-efi/gnuefi/elf_ia32_efi.lds @@ -0,0 +1,86 @@ +OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386") +OUTPUT_ARCH(i386) +ENTRY(_start) +SECTIONS +{ + . = 0; + ImageBase = .; + /* .hash and/or .gnu.hash MUST come first! */ + .hash : { *(.hash) } + .gnu.hash : { *(.gnu.hash) } + . = ALIGN(4096); + .text : + { + _text = .; + *(.text) + *(.text.*) + *(.gnu.linkonce.t.*) + . = ALIGN(16); + } + _etext = .; + _text_size = . - _text; + . = ALIGN(4096); + .sdata : + { + _data = .; + *(.got.plt) + *(.got) + *(.srodata) + *(.sdata) + *(.sbss) + *(.scommon) + } + . = ALIGN(4096); + .data : + { + *(.rodata*) + *(.data) + *(.data1) + *(.data.*) + *(.sdata) + *(.got.plt) + *(.got) + /* the EFI loader doesn't seem to like a .bss section, so we stick + it all into .data: */ + *(.sbss) + *(.scommon) + *(.dynbss) + *(.bss) + *(COMMON) + } + .note.gnu.build-id : { *(.note.gnu.build-id) } + + . = ALIGN(4096); + .dynamic : { *(.dynamic) } + . = ALIGN(4096); + .rel : + { + *(.rel.data) + *(.rel.data.*) + *(.rel.got) + *(.rel.stab) + *(.data.rel.ro.local) + *(.data.rel.local) + *(.data.rel.ro) + *(.data.rel*) + } + _edata = .; + _data_size = . - _etext; + . = ALIGN(4096); + .reloc : /* This is the PECOFF .reloc section! */ + { + *(.reloc) + } + . = ALIGN(4096); + .dynsym : { *(.dynsym) } + . = ALIGN(4096); + .dynstr : { *(.dynstr) } + . = ALIGN(4096); + /DISCARD/ : + { + *(.rel.reloc) + *(.eh_frame) + *(.note.GNU-stack) + } + .comment 0 : { *(.comment) } +} diff --git a/gnu-efi/gnuefi/elf_ia32_fbsd_efi.lds b/gnu-efi/gnuefi/elf_ia32_fbsd_efi.lds new file mode 100644 index 0000000..cd309e2 --- /dev/null +++ b/gnu-efi/gnuefi/elf_ia32_fbsd_efi.lds @@ -0,0 +1,86 @@ +OUTPUT_FORMAT("elf32-i386-freebsd", "elf32-i386-freebsd", "elf32-i386-freebsd") +OUTPUT_ARCH(i386) +ENTRY(_start) +SECTIONS +{ + . = 0; + ImageBase = .; + /* .hash and/or .gnu.hash MUST come first! */ + .hash : { *(.hash) } + .gnu.hash : { *(.gnu.hash) } + . = ALIGN(4096); + .text : + { + _text = .; + *(.text) + *(.text.*) + *(.gnu.linkonce.t.*) + . = ALIGN(16); + } + _etext = .; + _text_size = . - _text; + . = ALIGN(4096); + .sdata : + { + _data = .; + *(.got.plt) + *(.got) + *(.srodata) + *(.sdata) + *(.sbss) + *(.scommon) + } + . = ALIGN(4096); + .data : + { + *(.rodata*) + *(.data) + *(.data1) + *(.data.*) + *(.sdata) + *(.got.plt) + *(.got) + /* the EFI loader doesn't seem to like a .bss section, so we stick + it all into .data: */ + *(.sbss) + *(.scommon) + *(.dynbss) + *(.bss) + *(COMMON) + } + .note.gnu.build-id : { *(.note.gnu.build-id) } + + . = ALIGN(4096); + .dynamic : { *(.dynamic) } + . = ALIGN(4096); + .rel : + { + *(.rel.data) + *(.rel.data.*) + *(.rel.got) + *(.rel.stab) + *(.data.rel.ro.local) + *(.data.rel.local) + *(.data.rel.ro) + *(.data.rel*) + } + _edata = .; + _data_size = . - _etext; + . = ALIGN(4096); + .reloc : /* This is the PECOFF .reloc section! */ + { + *(.reloc) + } + . = ALIGN(4096); + .dynsym : { *(.dynsym) } + . = ALIGN(4096); + .dynstr : { *(.dynstr) } + . = ALIGN(4096); + /DISCARD/ : + { + *(.rel.reloc) + *(.eh_frame) + *(.note.GNU-stack) + } + .comment 0 : { *(.comment) } +} diff --git a/gnu-efi/gnuefi/elf_ia64_efi.lds b/gnu-efi/gnuefi/elf_ia64_efi.lds new file mode 100644 index 0000000..190792a --- /dev/null +++ b/gnu-efi/gnuefi/elf_ia64_efi.lds @@ -0,0 +1,81 @@ +OUTPUT_FORMAT("elf64-ia64-little") +OUTPUT_ARCH(ia64) +ENTRY(_start_plabel) +SECTIONS +{ + . = 0; + ImageBase = .; + /* .hash and/or .gnu.hash MUST come first! */ + .hash : { *(.hash) } + .gnu.hash : { *(.gnu.hash) } + . = ALIGN(4096); + .text : + { + _text = .; + *(.text) + *(.text.*) + *(.gnu.linkonce.t.*) + . = ALIGN(16); + } + _etext = .; + _text_size = . - _text; + . = ALIGN(4096); + __gp = ALIGN (8) + 0x200000; + .sdata : + { + _data = .; + *(.got.plt) + *(.got) + *(.srodata) + *(.sdata) + *(.sbss) + *(.scommon) + } + . = ALIGN(4096); + .data : + { + *(.rodata*) + *(.ctors) + *(.data*) + *(.gnu.linkonce.d*) + *(.plabel) /* data whose relocs we want to ignore */ + /* the EFI loader doesn't seem to like a .bss section, so we stick + it all into .data: */ + *(.dynbss) + *(.bss) + *(COMMON) + } + .note.gnu.build-id : { *(.note.gnu.build-id) } + + . = ALIGN(4096); + .dynamic : { *(.dynamic) } + . = ALIGN(4096); + .rela : + { + *(.rela.text) + *(.rela.data*) + *(.rela.sdata) + *(.rela.got) + *(.rela.gnu.linkonce.d*) + *(.rela.stab) + *(.rela.ctors) + } + _edata = .; + _data_size = . - _etext; + . = ALIGN(4096); + .reloc : /* This is the PECOFF .reloc section! */ + { + *(.reloc) + } + . = ALIGN(4096); + .dynsym : { *(.dynsym) } + . = ALIGN(4096); + .dynstr : { *(.dynstr) } + /DISCARD/ : + { + *(.rela.plabel) + *(.rela.reloc) + *(.IA_64.unwind*) + *(.IA64.unwind*) + } +} diff --git a/gnu-efi/gnuefi/elf_mips64el_efi.lds b/gnu-efi/gnuefi/elf_mips64el_efi.lds new file mode 100644 index 0000000..4d1a077 --- /dev/null +++ b/gnu-efi/gnuefi/elf_mips64el_efi.lds @@ -0,0 +1,64 @@ +OUTPUT_FORMAT("elf64-tradlittlemips", "elf64-tradbigmips", "elf64-tradlittlemips") +OUTPUT_ARCH(mips) +ENTRY(_start) +SECTIONS +{ + .text 0x0 : { + _text = .; + *(.text.head) + *(.text) + *(.text.*) + *(.gnu.linkonce.t.*) + *(.srodata) + *(.rodata*) + . = ALIGN(16); + } + _etext = .; + _text_size = . - _text; + .dynamic : { *(.dynamic) } + .data : + { + _data = .; + *(.sdata) + *(.data) + *(.data1) + *(.data.*) + *(.got.plt) + HIDDEN (_gp = ALIGN (16) + 0x7ff0); + *(.got) + + /* the EFI loader doesn't seem to like a .bss section, so we stick + it all into .data: */ + . = ALIGN(16); + _bss = .; + *(.sbss) + *(.scommon) + *(.dynbss) + *(.bss) + *(COMMON) + . = ALIGN(16); + _bss_end = .; + } + + .rel.dyn : { *(.rel.dyn) } + .rel.plt : { *(.rel.plt) } + .rel.got : { *(.rel.got) } + .rel.data : { *(.rel.data) *(.rel.data*) } + _edata = .; + _data_size = . - _etext; + + . = ALIGN(4096); + .dynsym : { *(.dynsym) } + . = ALIGN(4096); + .dynstr : { *(.dynstr) } + . = ALIGN(4096); + .note.gnu.build-id : { *(.note.gnu.build-id) } + /DISCARD/ : + { + *(.rel.reloc) + *(.eh_frame) + *(.MIPS.abiflags) + *(.note.GNU-stack) + } + .comment 0 : { *(.comment) } +} diff --git a/gnu-efi/gnuefi/elf_x86_64_efi.lds b/gnu-efi/gnuefi/elf_x86_64_efi.lds new file mode 100644 index 0000000..7be5902 --- /dev/null +++ b/gnu-efi/gnuefi/elf_x86_64_efi.lds @@ -0,0 +1,76 @@ +/* Same as elf_x86_64_fbsd_efi.lds, except for OUTPUT_FORMAT below - KEEP IN SYNC */ +OUTPUT_FORMAT("elf64-x86-64", "elf64-x86-64", "elf64-x86-64") +OUTPUT_ARCH(i386:x86-64) +ENTRY(_start) +SECTIONS +{ + . = 0; + ImageBase = .; + /* .hash and/or .gnu.hash MUST come first! */ + .hash : { *(.hash) } + .gnu.hash : { *(.gnu.hash) } + . = ALIGN(4096); + .eh_frame : + { + *(.eh_frame) + } + . = ALIGN(4096); + .text : + { + _text = .; + *(.text) + *(.text.*) + *(.gnu.linkonce.t.*) + . = ALIGN(16); + } + _etext = .; + _text_size = . - _text; + . = ALIGN(4096); + .reloc : + { + *(.reloc) + } + . = ALIGN(4096); + .data : + { + _data = .; + *(.rodata*) + *(.got.plt) + *(.got) + *(.data*) + *(.sdata) + /* the EFI loader doesn't seem to like a .bss section, so we stick + it all into .data: */ + *(.sbss) + *(.scommon) + *(.dynbss) + *(.bss) + *(COMMON) + *(.rel.local) + } + .note.gnu.build-id : { *(.note.gnu.build-id) } + + _edata = .; + _data_size = . - _etext; + . = ALIGN(4096); + .dynamic : { *(.dynamic) } + . = ALIGN(4096); + .rela : + { + *(.rela.data*) + *(.rela.got) + *(.rela.stab) + } + . = ALIGN(4096); + .dynsym : { *(.dynsym) } + . = ALIGN(4096); + .dynstr : { *(.dynstr) } + . = ALIGN(4096); + .ignored.reloc : + { + *(.rela.reloc) + *(.eh_frame) + *(.note.GNU-stack) + } + .comment 0 : { *(.comment) } +} diff --git a/gnu-efi/gnuefi/elf_x86_64_fbsd_efi.lds b/gnu-efi/gnuefi/elf_x86_64_fbsd_efi.lds new file mode 100644 index 0000000..fe1f334 --- /dev/null +++ b/gnu-efi/gnuefi/elf_x86_64_fbsd_efi.lds @@ -0,0 +1,70 @@ +/* Same as elf_x86_64_efi.lds, except for OUTPUT_FORMAT below - KEEP IN SYNC */ +OUTPUT_FORMAT("elf64-x86-64-freebsd", "elf64-x86-64-freebsd", "elf64-x86-64-freebsd") +OUTPUT_ARCH(i386:x86-64) +ENTRY(_start) +SECTIONS +{ + . = 0; + ImageBase = .; + /* .hash and/or .gnu.hash MUST come first! */ + .hash : { *(.hash) } + .gnu.hash : { *(.gnu.hash) } + . = ALIGN(4096); + .eh_frame : + { + *(.eh_frame) + } + . = ALIGN(4096); + .text : + { + _text = .; + *(.text) + . = ALIGN(16); + } + _etext = .; + _text_size = . - _text; + .reloc : + { + *(.reloc) + } + . = ALIGN(4096); + .data : + { + _data = .; + *(.rodata*) + *(.got.plt) + *(.got) + *(.data*) + *(.sdata) + /* the EFI loader doesn't seem to like a .bss section, so we stick + it all into .data: */ + *(.sbss) + *(.scommon) + *(.dynbss) + *(.bss) + *(COMMON) + *(.rel.local) + } + .note.gnu.build-id : { *(.note.gnu.build-id) } + + . = ALIGN(4096); + .dynamic : { *(.dynamic) } + . = ALIGN(4096); + .rela : + { + *(.rela.data*) + *(.rela.got) + *(.rela.stab) + } + _edata = .; + _data_size = . - _etext; + . = ALIGN(4096); + .dynsym : { *(.dynsym) } + . = ALIGN(4096); + .dynstr : { *(.dynstr) } + . = ALIGN(4096); + .ignored.reloc : + { + *(.rela.reloc) + } +} diff --git a/gnu-efi/gnuefi/reloc_aarch64.c b/gnu-efi/gnuefi/reloc_aarch64.c new file mode 100644 index 0000000..0867279 --- /dev/null +++ b/gnu-efi/gnuefi/reloc_aarch64.c @@ -0,0 +1,97 @@ +/* reloc_aarch64.c - position independent x86 ELF shared object relocator + Copyright (C) 2014 Linaro Ltd. + Copyright (C) 1999 Hewlett-Packard Co. + Contributed by David Mosberger . + + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials + provided with the distribution. + * Neither the name of Hewlett-Packard Co. nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + BE LIABLE FOR ANYDIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF + THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. +*/ + +#include +#include + +#include + +EFI_STATUS _relocate (long ldbase, Elf64_Dyn *dyn, + EFI_HANDLE image EFI_UNUSED, + EFI_SYSTEM_TABLE *systab EFI_UNUSED) +{ + long relsz = 0, relent = 0; + Elf64_Rela *rel = 0; + unsigned long *addr; + int i; + + for (i = 0; dyn[i].d_tag != DT_NULL; ++i) { + switch (dyn[i].d_tag) { + case DT_RELA: + rel = (Elf64_Rela*) + ((unsigned long)dyn[i].d_un.d_ptr + + ldbase); + break; + + case DT_RELASZ: + relsz = dyn[i].d_un.d_val; + break; + + case DT_RELAENT: + relent = dyn[i].d_un.d_val; + break; + + default: + break; + } + } + + if (!rel && relent == 0) + return EFI_SUCCESS; + + if (!rel || relent == 0) + return EFI_LOAD_ERROR; + + while (relsz > 0) { + /* apply the relocs */ + switch (ELF64_R_TYPE (rel->r_info)) { + case R_AARCH64_NONE: + break; + + case R_AARCH64_RELATIVE: + addr = (unsigned long *) + (ldbase + rel->r_offset); + *addr = ldbase + rel->r_addend; + break; + + default: + break; + } + rel = (Elf64_Rela*) ((char *) rel + relent); + relsz -= relent; + } + return EFI_SUCCESS; +} diff --git a/gnu-efi/gnuefi/reloc_arm.c b/gnu-efi/gnuefi/reloc_arm.c new file mode 100644 index 0000000..7585066 --- /dev/null +++ b/gnu-efi/gnuefi/reloc_arm.c @@ -0,0 +1,97 @@ +/* reloc_arm.c - position independent x86 ELF shared object relocator + Copyright (C) 2014 Linaro Ltd. + Copyright (C) 1999 Hewlett-Packard Co. + Contributed by David Mosberger . + + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials + provided with the distribution. + * Neither the name of Hewlett-Packard Co. nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + BE LIABLE FOR ANYDIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF + THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. +*/ + +#include +#include + +#include + +EFI_STATUS _relocate (long ldbase, Elf32_Dyn *dyn, + EFI_HANDLE image EFI_UNUSED, + EFI_SYSTEM_TABLE *systab EFI_UNUSED) +{ + long relsz = 0, relent = 0; + Elf32_Rel *rel = 0; + unsigned long *addr; + int i; + + for (i = 0; dyn[i].d_tag != DT_NULL; ++i) { + switch (dyn[i].d_tag) { + case DT_REL: + rel = (Elf32_Rel*) + ((unsigned long)dyn[i].d_un.d_ptr + + ldbase); + break; + + case DT_RELSZ: + relsz = dyn[i].d_un.d_val; + break; + + case DT_RELENT: + relent = dyn[i].d_un.d_val; + break; + + default: + break; + } + } + + if (!rel && relent == 0) + return EFI_SUCCESS; + + if (!rel || relent == 0) + return EFI_LOAD_ERROR; + + while (relsz > 0) { + /* apply the relocs */ + switch (ELF32_R_TYPE (rel->r_info)) { + case R_ARM_NONE: + break; + + case R_ARM_RELATIVE: + addr = (unsigned long *) + (ldbase + rel->r_offset); + *addr += ldbase; + break; + + default: + break; + } + rel = (Elf32_Rel*) ((char *) rel + relent); + relsz -= relent; + } + return EFI_SUCCESS; +} diff --git a/gnu-efi/gnuefi/reloc_ia32.c b/gnu-efi/gnuefi/reloc_ia32.c new file mode 100644 index 0000000..da9d8a7 --- /dev/null +++ b/gnu-efi/gnuefi/reloc_ia32.c @@ -0,0 +1,99 @@ +/* reloc_ia32.c - position independent x86 ELF shared object relocator + Copyright (C) 1999 Hewlett-Packard Co. + Contributed by David Mosberger . + + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials + provided with the distribution. + * Neither the name of Hewlett-Packard Co. nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + BE LIABLE FOR ANYDIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF + THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. +*/ + +#include +#include + +#include + +EFI_STATUS _relocate (long ldbase, Elf32_Dyn *dyn, + EFI_HANDLE image EFI_UNUSED, + EFI_SYSTEM_TABLE *systab EFI_UNUSED) +{ + long relsz = 0, relent = 0; + Elf32_Rel *rel = 0; + unsigned long *addr; + int i; + + for (i = 0; dyn[i].d_tag != DT_NULL; ++i) { + switch (dyn[i].d_tag) { + case DT_REL: + rel = (Elf32_Rel*) + ((unsigned long)dyn[i].d_un.d_ptr + + ldbase); + break; + + case DT_RELSZ: + relsz = dyn[i].d_un.d_val; + break; + + case DT_RELENT: + relent = dyn[i].d_un.d_val; + break; + + case DT_RELA: + break; + + default: + break; + } + } + + if (!rel && relent == 0) + return EFI_SUCCESS; + + if (!rel || relent == 0) + return EFI_LOAD_ERROR; + + while (relsz > 0) { + /* apply the relocs */ + switch (ELF32_R_TYPE (rel->r_info)) { + case R_386_NONE: + break; + + case R_386_RELATIVE: + addr = (unsigned long *) + (ldbase + rel->r_offset); + *addr += ldbase; + break; + + default: + break; + } + rel = (Elf32_Rel*) ((char *) rel + relent); + relsz -= relent; + } + return EFI_SUCCESS; +} diff --git a/gnu-efi/gnuefi/reloc_ia64.S b/gnu-efi/gnuefi/reloc_ia64.S new file mode 100644 index 0000000..40203bf --- /dev/null +++ b/gnu-efi/gnuefi/reloc_ia64.S @@ -0,0 +1,227 @@ +/* reloc_ia64.S - position independent IA-64 ELF shared object relocator + Copyright (C) 1999 Hewlett-Packard Co. + Contributed by David Mosberger . + + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials + provided with the distribution. + * Neither the name of Hewlett-Packard Co. nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + BE LIABLE FOR ANYDIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF + THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. +*/ + +/* + * This is written in assembly because the entire code needs to be position + * independent. Note that the compiler does not generate code that's position + * independent by itself because it relies on the global offset table being + * relocated. + */ + .text + .psr abi64 + .psr lsb + .lsb + +/* + * This constant determines how many R_IA64_FPTR64LSB relocations we + * can deal with. If you get EFI_BUFFER_TOO_SMALL errors, you may + * need to increase this number. + */ +#define MAX_FUNCTION_DESCRIPTORS 750 + +#define ST_VALUE_OFF 8 /* offset of st_value in elf sym */ + +#define EFI_SUCCESS 0 +#define EFI_LOAD_ERROR 1 +#define EFI_BUFFER_TOO_SMALL 5 + +#define DT_NULL 0 /* Marks end of dynamic section */ +#define DT_RELA 7 /* Address of Rela relocs */ +#define DT_RELASZ 8 /* Total size of Rela relocs */ +#define DT_RELAENT 9 /* Size of one Rela reloc */ +#define DT_SYMTAB 6 /* Address of symbol table */ +#define DT_SYMENT 11 /* Size of one symbol table entry */ + +#define R_IA64_NONE 0 +#define R_IA64_REL64MSB 0x6e +#define R_IA64_REL64LSB 0x6f +#define R_IA64_DIR64MSB 0x26 +#define R_IA64_DIR64LSB 0x27 +#define R_IA64_FPTR64MSB 0x46 +#define R_IA64_FPTR64LSB 0x47 + +#define ldbase in0 /* load address (address of .text) */ +#define dyn in1 /* address of _DYNAMIC */ + +#define d_tag r16 +#define d_val r17 +#define rela r18 +#define relasz r19 +#define relaent r20 +#define addr r21 +#define r_info r22 +#define r_offset r23 +#define r_addend r24 +#define r_type r25 +#define r_sym r25 /* alias of r_type ! */ +#define fptr r26 +#define fptr_limit r27 +#define symtab f8 +#define syment f9 +#define ftmp f10 + +#define target r16 +#define val r17 + +#define NLOC 0 + +#define Pnull p6 +#define Prela p7 +#define Prelasz p8 +#define Prelaent p9 +#define Psymtab p10 +#define Psyment p11 + +#define Pnone p6 +#define Prel p7 +#define Pfptr p8 + +#define Pmore p6 + +#define Poom p6 /* out-of-memory */ + + .global _relocate + .proc _relocate +_relocate: + alloc r2=ar.pfs,2,0,0,0 + movl fptr = @gprel(fptr_mem_base) + ;; + add fptr = fptr, gp + movl fptr_limit = @gprel(fptr_mem_limit) + ;; + add fptr_limit = fptr_limit, gp + +search_dynamic: + ld8 d_tag = [dyn],8 + ;; + ld8 d_val = [dyn],8 + cmp.eq Pnull,p0 = DT_NULL,d_tag +(Pnull) br.cond.sptk.few apply_relocs + cmp.eq Prela,p0 = DT_RELA,d_tag + cmp.eq Prelasz,p0 = DT_RELASZ,d_tag + cmp.eq Psymtab,p0 = DT_SYMTAB,d_tag + cmp.eq Psyment,p0 = DT_SYMENT,d_tag + cmp.eq Prelaent,p0 = DT_RELAENT,d_tag + ;; +(Prela) add rela = d_val, ldbase +(Prelasz) mov relasz = d_val +(Prelaent) mov relaent = d_val +(Psymtab) add val = d_val, ldbase + ;; +(Psyment) setf.sig syment = d_val + ;; +(Psymtab) setf.sig symtab = val + br.sptk.few search_dynamic + +apply_loop: + ld8 r_offset = [rela] + add addr = 8,rela + sub relasz = relasz,relaent + ;; + + ld8 r_info = [addr],8 + ;; + ld8 r_addend = [addr] + add target = ldbase, r_offset + + add rela = rela,relaent + extr.u r_type = r_info, 0, 32 + ;; + cmp.eq Pnone,p0 = R_IA64_NONE,r_type + cmp.eq Prel,p0 = R_IA64_REL64LSB,r_type + cmp.eq Pfptr,p0 = R_IA64_FPTR64LSB,r_type +(Prel) br.cond.sptk.few apply_REL64 + ;; + cmp.eq Prel,p0 = R_IA64_DIR64LSB,r_type // treat DIR64 just like REL64 + +(Pnone) br.cond.sptk.few apply_relocs +(Prel) br.cond.sptk.few apply_REL64 +(Pfptr) br.cond.sptk.few apply_FPTR64 + + mov r8 = EFI_LOAD_ERROR + br.ret.sptk.few rp + +apply_relocs: + cmp.ltu Pmore,p0=0,relasz +(Pmore) br.cond.sptk.few apply_loop + + mov r8 = EFI_SUCCESS + br.ret.sptk.few rp + +apply_REL64: + ld8 val = [target] + ;; + add val = val,ldbase + ;; + st8 [target] = val + br.cond.sptk.few apply_relocs + + // FPTR relocs are a bit more interesting: we need to lookup + // the symbol's value in symtab, allocate 16 bytes of memory, + // store the value in [target] in the first and the gp in the + // second dword. +apply_FPTR64: + st8 [target] = fptr + extr.u r_sym = r_info,32,32 + add target = 8,fptr + ;; + + setf.sig ftmp = r_sym + mov r8=EFI_BUFFER_TOO_SMALL + ;; + cmp.geu Poom,p0 = fptr,fptr_limit + + xma.lu ftmp = ftmp,syment,symtab +(Poom) br.ret.sptk.few rp + ;; + getf.sig addr = ftmp + st8 [target] = gp + ;; + add addr = ST_VALUE_OFF, addr + ;; + ld8 val = [addr] + ;; + add val = val,ldbase + ;; + st8 [fptr] = val,16 + br.cond.sptk.few apply_relocs + + .endp _relocate + + .data + .align 16 +fptr_mem_base: + .space MAX_FUNCTION_DESCRIPTORS*16 +fptr_mem_limit: diff --git a/gnu-efi/gnuefi/reloc_mips64el.c b/gnu-efi/gnuefi/reloc_mips64el.c new file mode 100644 index 0000000..4db21ad --- /dev/null +++ b/gnu-efi/gnuefi/reloc_mips64el.c @@ -0,0 +1,115 @@ +/* reloc_mips64el.c - position independent MIPS64 ELF shared object relocator + Copyright (C) 2014 Linaro Ltd. + Copyright (C) 1999 Hewlett-Packard Co. + Contributed by David Mosberger . + Copyright (C) 2017 Lemote Co. + Contributed by Heiher + + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials + provided with the distribution. + * Neither the name of Hewlett-Packard Co. nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + BE LIABLE FOR ANYDIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF + THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. +*/ + +#include +#include + +#include + +EFI_STATUS _relocate (long ldbase, Elf64_Dyn *dyn, + EFI_HANDLE image EFI_UNUSED, + EFI_SYSTEM_TABLE *systab EFI_UNUSED) +{ + long relsz = 0, relent = 0, gotsz = 0; + Elf64_Rel *rel = 0; + unsigned long *addr = 0; + int i; + + for (i = 0; dyn[i].d_tag != DT_NULL; ++i) { + switch (dyn[i].d_tag) { + case DT_REL: + rel = (Elf64_Rel*) + ((unsigned long)dyn[i].d_un.d_ptr + + ldbase); + break; + + case DT_RELSZ: + relsz = dyn[i].d_un.d_val; + break; + + case DT_RELENT: + relent = dyn[i].d_un.d_val; + break; + + case DT_PLTGOT: + addr = (unsigned long *) + ((unsigned long)dyn[i].d_un.d_ptr + + ldbase); + break; + + case DT_MIPS_LOCAL_GOTNO: + gotsz = dyn[i].d_un.d_val; + break; + + default: + break; + } + } + + if ((!rel && relent == 0) && (!addr && gotsz == 0)) + return EFI_SUCCESS; + + if ((!rel && relent != 0) || (!addr && gotsz != 0)) + return EFI_LOAD_ERROR; + + while (gotsz > 0) { + *addr += ldbase; + addr += 1; + gotsz --; + } + + while (relsz > 0) { + /* apply the relocs */ + switch (ELF64_R_TYPE (swap_uint64 (rel->r_info))) { + case R_MIPS_NONE: + break; + + case (R_MIPS_64 << 8) | R_MIPS_REL32: + addr = (unsigned long *) + (ldbase + rel->r_offset); + *addr += ldbase; + break; + + default: + break; + } + rel = (Elf64_Rel*) ((char *) rel + relent); + relsz -= relent; + } + return EFI_SUCCESS; +} diff --git a/gnu-efi/gnuefi/reloc_x86_64.c b/gnu-efi/gnuefi/reloc_x86_64.c new file mode 100644 index 0000000..04b75b2 --- /dev/null +++ b/gnu-efi/gnuefi/reloc_x86_64.c @@ -0,0 +1,98 @@ +/* reloc_x86_64.c - position independent x86_64 ELF shared object relocator + Copyright (C) 1999 Hewlett-Packard Co. + Contributed by David Mosberger . + Copyright (C) 2005 Intel Co. + Contributed by Fenghua Yu . + + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials + provided with the distribution. + * Neither the name of Hewlett-Packard Co. nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + BE LIABLE FOR ANYDIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF + THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. +*/ + +#include +#include + +#include + +EFI_STATUS _relocate (long ldbase, Elf64_Dyn *dyn, + EFI_HANDLE image EFI_UNUSED, + EFI_SYSTEM_TABLE *systab EFI_UNUSED) +{ + long relsz = 0, relent = 0; + Elf64_Rel *rel = 0; + unsigned long *addr; + int i; + + for (i = 0; dyn[i].d_tag != DT_NULL; ++i) { + switch (dyn[i].d_tag) { + case DT_RELA: + rel = (Elf64_Rel*) + ((unsigned long)dyn[i].d_un.d_ptr + + ldbase); + break; + + case DT_RELASZ: + relsz = dyn[i].d_un.d_val; + break; + + case DT_RELAENT: + relent = dyn[i].d_un.d_val; + break; + + default: + break; + } + } + + if (!rel && relent == 0) + return EFI_SUCCESS; + + if (!rel || relent == 0) + return EFI_LOAD_ERROR; + + while (relsz > 0) { + /* apply the relocs */ + switch (ELF64_R_TYPE (rel->r_info)) { + case R_X86_64_NONE: + break; + + case R_X86_64_RELATIVE: + addr = (unsigned long *) + (ldbase + rel->r_offset); + *addr += ldbase; + break; + + default: + break; + } + rel = (Elf64_Rel*) ((char *) rel + relent); + relsz -= relent; + } + return EFI_SUCCESS; +} diff --git a/gnu-efi/inc/Makefile b/gnu-efi/inc/Makefile new file mode 100644 index 0000000..273d303 --- /dev/null +++ b/gnu-efi/inc/Makefile @@ -0,0 +1,27 @@ +SRCDIR = . + +VPATH = $(SRCDIR) + +include $(SRCDIR)/../Make.defaults + +TOPDIR = $(SRCDIR)/.. + +CDIR=$(TOPDIR)/.. + +all: + +clean: + +install: + mkdir -p $(INSTALLROOT)$(PREFIX)/include/efi + mkdir -p $(INSTALLROOT)$(PREFIX)/include/efi/protocol + mkdir -p $(INSTALLROOT)$(PREFIX)/include/efi/$(ARCH) + $(INSTALL) -m 644 $(SRCDIR)/*.h $(INSTALLROOT)$(PREFIX)/include/efi + $(INSTALL) -m 644 $(SRCDIR)/protocol/*.h $(INSTALLROOT)$(PREFIX)/include/efi/protocol + $(INSTALL) -m 644 $(SRCDIR)/$(ARCH)/*.h $(INSTALLROOT)$(PREFIX)/include/efi/$(ARCH) +ifeq ($(ARCH),ia64) + mkdir -p $(INSTALLROOT)$(PREFIX)/include/efi/protocol/ia64 + $(INSTALL) -m 644 $(SRCDIR)/protocol/ia64/*.h $(INSTALLROOT)$(PREFIX)/include/efi/protocol/ia64 +endif + +include $(SRCDIR)/../Make.rules diff --git a/gnu-efi/inc/aarch64/efibind.h b/gnu-efi/inc/aarch64/efibind.h new file mode 100644 index 0000000..c2c546b --- /dev/null +++ b/gnu-efi/inc/aarch64/efibind.h @@ -0,0 +1,158 @@ +/* + * Copright (C) 2014 - 2015 Linaro Ltd. + * Author: Ard Biesheuvel + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice and this list of conditions, without modification. + * 2. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * Alternatively, this software may be distributed 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. + */ + +#if !defined(_MSC_VER) && (!defined(__STDC_VERSION__) || (__STDC_VERSION__ < 199901L )) && !defined(__cplusplus) + +// ANSI C 1999/2000 stdint.h integer width declarations + +typedef unsigned long uint64_t; +typedef long int64_t; +typedef unsigned int uint32_t; +typedef int int32_t; +typedef unsigned short uint16_t; +typedef short int16_t; +typedef unsigned char uint8_t; +typedef signed char int8_t; // unqualified 'char' is unsigned on ARM +typedef uint64_t uintptr_t; +typedef int64_t intptr_t; + +#else +#include +#endif + +// +// Basic EFI types of various widths +// + +#ifndef __WCHAR_TYPE__ +# define __WCHAR_TYPE__ short +#endif + +typedef uint64_t UINT64; +typedef int64_t INT64; + +typedef uint32_t UINT32; +typedef int32_t INT32; + +typedef uint16_t UINT16; +typedef int16_t INT16; +typedef uint8_t UINT8; +typedef int8_t INT8; +typedef __WCHAR_TYPE__ WCHAR; + +#undef VOID +#define VOID void + +typedef int64_t INTN; +typedef uint64_t UINTN; + +#define EFIERR(a) (0x8000000000000000 | a) +#define EFI_ERROR_MASK 0x8000000000000000 +#define EFIERR_OEM(a) (0xc000000000000000 | a) + +#define BAD_POINTER 0xFBFBFBFBFBFBFBFB +#define MAX_ADDRESS 0xFFFFFFFFFFFFFFFF + +#define BREAKPOINT() while (TRUE); // Make it hang on Bios[Dbg]32 + +// +// Pointers must be aligned to these address to function +// + +#define MIN_ALIGNMENT_SIZE 8 + +#define ALIGN_VARIABLE(Value ,Adjustment) \ + (UINTN)Adjustment = 0; \ + if((UINTN)Value % MIN_ALIGNMENT_SIZE) \ + (UINTN)Adjustment = MIN_ALIGNMENT_SIZE - ((UINTN)Value % MIN_ALIGNMENT_SIZE); \ + Value = (UINTN)Value + (UINTN)Adjustment + + +// +// Define macros to build data structure signatures from characters. +// + +#define EFI_SIGNATURE_16(A,B) ((A) | (B<<8)) +#define EFI_SIGNATURE_32(A,B,C,D) (EFI_SIGNATURE_16(A,B) | (EFI_SIGNATURE_16(C,D) << 16)) +#define EFI_SIGNATURE_64(A,B,C,D,E,F,G,H) (EFI_SIGNATURE_32(A,B,C,D) | ((UINT64)(EFI_SIGNATURE_32(E,F,G,H)) << 32)) + +// +// EFIAPI - prototype calling convention for EFI function pointers +// BOOTSERVICE - prototype for implementation of a boot service interface +// RUNTIMESERVICE - prototype for implementation of a runtime service interface +// RUNTIMEFUNCTION - prototype for implementation of a runtime function that is not a service +// RUNTIME_CODE - pragma macro for declaring runtime code +// + +#ifndef EFIAPI // Forces EFI calling conventions reguardless of compiler options +#define EFIAPI // Substitute expresion to force C calling convention +#endif + +#define BOOTSERVICE +#define RUNTIMESERVICE +#define RUNTIMEFUNCTION + + +#define RUNTIME_CODE(a) alloc_text("rtcode", a) +#define BEGIN_RUNTIME_DATA() data_seg("rtdata") +#define END_RUNTIME_DATA() data_seg("") + +#define VOLATILE volatile + +#define MEMORY_FENCE __sync_synchronize + +// +// When build similiar to FW, then link everything together as +// one big module. For the MSVC toolchain, we simply tell the +// linker what our driver init function is using /ENTRY. +// +#if defined(_MSC_EXTENSIONS) +#define EFI_DRIVER_ENTRY_POINT(InitFunction) \ + __pragma(comment(linker, "/ENTRY:" # InitFunction)) +#else +#define EFI_DRIVER_ENTRY_POINT(InitFunction) \ + UINTN \ + InitializeDriver ( \ + VOID *ImageHandle, \ + VOID *SystemTable \ + ) \ + { \ + return InitFunction(ImageHandle, \ + SystemTable); \ + } \ + \ + EFI_STATUS efi_main( \ + EFI_HANDLE image, \ + EFI_SYSTEM_TABLE *systab \ + ) __attribute__((weak, \ + alias ("InitializeDriver"))); +#endif + +#define LOAD_INTERNAL_DRIVER(_if, type, name, entry) \ + (_if)->LoadInternal(type, name, entry) + + +// +// Some compilers don't support the forward reference construct: +// typedef struct XXXXX +// +// The following macro provide a workaround for such cases. + +#define INTERFACE_DECL(x) struct x + +#define uefi_call_wrapper(func, va_num, ...) func(__VA_ARGS__) +#define EFI_FUNCTION diff --git a/gnu-efi/inc/aarch64/efilibplat.h b/gnu-efi/inc/aarch64/efilibplat.h new file mode 100644 index 0000000..70a0786 --- /dev/null +++ b/gnu-efi/inc/aarch64/efilibplat.h @@ -0,0 +1,25 @@ +/*++ + +Copyright (c) 1998 Intel Corporation + +Module Name: + + efilibplat.h + +Abstract: + + EFI to compile bindings + + + + +Revision History + +--*/ + +VOID +InitializeLibPlatform ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + diff --git a/gnu-efi/inc/aarch64/efisetjmp_arch.h b/gnu-efi/inc/aarch64/efisetjmp_arch.h new file mode 100644 index 0000000..8dbce07 --- /dev/null +++ b/gnu-efi/inc/aarch64/efisetjmp_arch.h @@ -0,0 +1,33 @@ +#ifndef GNU_EFI_AARCH64_SETJMP_H +#define GNU_EFI_AARCH64_SETJMP_H + +#define JMPBUF_ALIGN 8 + +typedef struct { + /* GP regs */ + UINT64 X19; + UINT64 X20; + UINT64 X21; + UINT64 X22; + UINT64 X23; + UINT64 X24; + UINT64 X25; + UINT64 X26; + UINT64 X27; + UINT64 X28; + UINT64 FP; + UINT64 LR; + UINT64 IP0; + + /* FP regs */ + UINT64 D8; + UINT64 D9; + UINT64 D10; + UINT64 D11; + UINT64 D12; + UINT64 D13; + UINT64 D14; + UINT64 D15; +} ALIGN(JMPBUF_ALIGN) jmp_buf[1]; + +#endif /* GNU_EFI_AARCH64_SETJMP_H */ diff --git a/gnu-efi/inc/arm/efibind.h b/gnu-efi/inc/arm/efibind.h new file mode 100644 index 0000000..012d3d2 --- /dev/null +++ b/gnu-efi/inc/arm/efibind.h @@ -0,0 +1,166 @@ +/* + * Copright (C) 2014 - 2015 Linaro Ltd. + * Author: Ard Biesheuvel + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice and this list of conditions, without modification. + * 2. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * Alternatively, this software may be distributed 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. + */ + +#if !defined(_MSC_VER) && (!defined(__STDC_VERSION__) || (__STDC_VERSION__ < 199901L )) && !defined(__cplusplus) + +// ANSI C 1999/2000 stdint.h integer width declarations + +typedef unsigned long long uint64_t; +typedef long long int64_t; +typedef unsigned int uint32_t; +typedef int int32_t; +typedef unsigned short uint16_t; +typedef short int16_t; +typedef unsigned char uint8_t; +typedef signed char int8_t; // unqualified 'char' is unsigned on ARM +typedef uint32_t uintptr_t; +typedef int32_t intptr_t; + +#else +#include +#endif + +/* + * This prevents GCC from emitting GOT based relocations, and use R_ARM_REL32 + * relative relocations instead, which are more suitable for static binaries. + */ +#ifdef __GNUC__ +#pragma GCC visibility push (hidden) +#endif + +// +// Basic EFI types of various widths +// + +#ifndef __WCHAR_TYPE__ +# define __WCHAR_TYPE__ short +#endif + +typedef uint64_t UINT64; +typedef int64_t INT64; + +typedef uint32_t UINT32; +typedef int32_t INT32; + +typedef uint16_t UINT16; +typedef int16_t INT16; +typedef uint8_t UINT8; +typedef int8_t INT8; +typedef __WCHAR_TYPE__ WCHAR; + +#undef VOID +#define VOID void + +typedef int32_t INTN; +typedef uint32_t UINTN; + +#define EFIERR(a) (0x80000000 | a) +#define EFI_ERROR_MASK 0x80000000 +#define EFIERR_OEM(a) (0xc0000000 | a) + +#define BAD_POINTER 0xFBFBFBFB +#define MAX_ADDRESS 0xFFFFFFFF + +#define BREAKPOINT() while (TRUE); + +// +// Pointers must be aligned to these address to function +// + +#define MIN_ALIGNMENT_SIZE 4 + +#define ALIGN_VARIABLE(Value ,Adjustment) \ + (UINTN)Adjustment = 0; \ + if((UINTN)Value % MIN_ALIGNMENT_SIZE) \ + (UINTN)Adjustment = MIN_ALIGNMENT_SIZE - ((UINTN)Value % MIN_ALIGNMENT_SIZE); \ + Value = (UINTN)Value + (UINTN)Adjustment + + +// +// Define macros to build data structure signatures from characters. +// + +#define EFI_SIGNATURE_16(A,B) ((A) | (B<<8)) +#define EFI_SIGNATURE_32(A,B,C,D) (EFI_SIGNATURE_16(A,B) | (EFI_SIGNATURE_16(C,D) << 16)) +#define EFI_SIGNATURE_64(A,B,C,D,E,F,G,H) (EFI_SIGNATURE_32(A,B,C,D) | ((UINT64)(EFI_SIGNATURE_32(E,F,G,H)) << 32)) + +// +// EFIAPI - prototype calling convention for EFI function pointers +// BOOTSERVICE - prototype for implementation of a boot service interface +// RUNTIMESERVICE - prototype for implementation of a runtime service interface +// RUNTIMEFUNCTION - prototype for implementation of a runtime function that is not a service +// RUNTIME_CODE - pragma macro for declaring runtime code +// + +#ifndef EFIAPI // Forces EFI calling conventions reguardless of compiler options +#define EFIAPI // Substitute expresion to force C calling convention +#endif + +#define BOOTSERVICE +#define RUNTIMESERVICE +#define RUNTIMEFUNCTION + + +#define RUNTIME_CODE(a) alloc_text("rtcode", a) +#define BEGIN_RUNTIME_DATA() data_seg("rtdata") +#define END_RUNTIME_DATA() data_seg("") + +#define VOLATILE volatile + +#define MEMORY_FENCE __sync_synchronize + +// +// When build similiar to FW, then link everything together as +// one big module. For the MSVC toolchain, we simply tell the +// linker what our driver init function is using /ENTRY. +// +#if defined(_MSC_EXTENSIONS) +#define EFI_DRIVER_ENTRY_POINT(InitFunction) \ + __pragma(comment(linker, "/ENTRY:" # InitFunction)) +#else +#define EFI_DRIVER_ENTRY_POINT(InitFunction) \ + UINTN \ + InitializeDriver ( \ + VOID *ImageHandle, \ + VOID *SystemTable \ + ) \ + { \ + return InitFunction(ImageHandle, \ + SystemTable); \ + } \ + \ + EFI_STATUS efi_main( \ + EFI_HANDLE image, \ + EFI_SYSTEM_TABLE *systab \ + ) __attribute__((weak, \ + alias ("InitializeDriver"))); +#endif + +#define LOAD_INTERNAL_DRIVER(_if, type, name, entry) \ + (_if)->LoadInternal(type, name, entry) + + +// +// Some compilers don't support the forward reference construct: +// typedef struct XXXXX +// +// The following macro provide a workaround for such cases. + +#define INTERFACE_DECL(x) struct x + +#define uefi_call_wrapper(func, va_num, ...) func(__VA_ARGS__) +#define EFI_FUNCTION diff --git a/gnu-efi/inc/arm/efilibplat.h b/gnu-efi/inc/arm/efilibplat.h new file mode 100644 index 0000000..70a0786 --- /dev/null +++ b/gnu-efi/inc/arm/efilibplat.h @@ -0,0 +1,25 @@ +/*++ + +Copyright (c) 1998 Intel Corporation + +Module Name: + + efilibplat.h + +Abstract: + + EFI to compile bindings + + + + +Revision History + +--*/ + +VOID +InitializeLibPlatform ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + diff --git a/gnu-efi/inc/arm/efisetjmp_arch.h b/gnu-efi/inc/arm/efisetjmp_arch.h new file mode 100644 index 0000000..17f5dc0 --- /dev/null +++ b/gnu-efi/inc/arm/efisetjmp_arch.h @@ -0,0 +1,21 @@ +#ifndef GNU_EFI_ARM_SETJMP_H +#define GNU_EFI_ARM_SETJMP_H + +#define JMPBUF_ALIGN 4 + +typedef struct { + UINT32 R3; // A copy of R13 + UINT32 R4; + UINT32 R5; + UINT32 R6; + UINT32 R7; + UINT32 R8; + UINT32 R9; + UINT32 R10; + UINT32 R11; + UINT32 R12; + UINT32 R13; + UINT32 R14; +} ALIGN(JMPBUF_ALIGN) jmp_buf[1]; + +#endif /* GNU_EFI_ARM_SETJMP_H */ diff --git a/gnu-efi/inc/efi.h b/gnu-efi/inc/efi.h new file mode 100644 index 0000000..2ddd53e --- /dev/null +++ b/gnu-efi/inc/efi.h @@ -0,0 +1,61 @@ +/*++ + +Copyright (c) 1998 Intel Corporation + +Module Name: + + efi.h + +Abstract: + + Public EFI header files + + + +Revision History + +--*/ + + +// Add a predefined macro to detect usage of the library +#ifndef _GNU_EFI +#define _GNU_EFI +#endif + +// +// Build flags on input +// EFI32 +// EFI_DEBUG - Enable debugging code +// EFI_NT_EMULATOR - Building for running under NT +// + + +#ifndef _EFI_INCLUDE_ +#define _EFI_INCLUDE_ + +#define EFI_FIRMWARE_VENDOR L"INTEL" +#define EFI_FIRMWARE_MAJOR_REVISION 12 +#define EFI_FIRMWARE_MINOR_REVISION 33 +#define EFI_FIRMWARE_REVISION ((EFI_FIRMWARE_MAJOR_REVISION <<16) | (EFI_FIRMWARE_MINOR_REVISION)) + +#include "efibind.h" +#include "eficompiler.h" +#include "efidef.h" +#include "efidevp.h" +#include "efipciio.h" +#include "efiprot.h" +#include "eficon.h" +#include "efiser.h" +#include "efi_nii.h" +#include "efipxebc.h" +#include "efinet.h" +#include "efiapi.h" +#include "efifs.h" +#include "efierr.h" +#include "efiui.h" +#include "efiip.h" +#include "efiudp.h" +#include "efitcp.h" +#include "efipoint.h" + +#endif diff --git a/gnu-efi/inc/efi_nii.h b/gnu-efi/inc/efi_nii.h new file mode 100644 index 0000000..fdf5cb4 --- /dev/null +++ b/gnu-efi/inc/efi_nii.h @@ -0,0 +1,78 @@ +#ifndef _EFI_NII_H +#define _EFI_NII_H + +/*++ +Copyright (c) 2000 Intel Corporation + +Module name: + efi_nii.h + +Abstract: + +Revision history: + 2000-Feb-18 M(f)J GUID updated. + Structure order changed for machine word alignment. + Added StringId[4] to structure. + + 2000-Feb-14 M(f)J Genesis. +--*/ + +#define EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL_GUID \ + { 0xE18541CD, 0xF755, 0x4f73, {0x92, 0x8D, 0x64, 0x3C, 0x8A, 0x79, 0xB2, 0x29} } + +#define EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL_REVISION 0x00010000 +#define EFI_NETWORK_INTERFACE_IDENTIFIER_INTERFACE_REVISION EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL_REVISION + +typedef enum { + EfiNetworkInterfaceUndi = 1 +} EFI_NETWORK_INTERFACE_TYPE; + +typedef struct _EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL { + + UINT64 Revision; + // Revision of the network interface identifier protocol interface. + + UINT64 ID; + // Address of the first byte of the identifying structure for this + // network interface. This is set to zero if there is no structure. + // + // For PXE/UNDI this is the first byte of the !PXE structure. + + UINT64 ImageAddr; + // Address of the UNrelocated driver/ROM image. This is set + // to zero if there is no driver/ROM image. + // + // For 16-bit UNDI, this is the first byte of the option ROM in + // upper memory. + // + // For 32/64-bit S/W UNDI, this is the first byte of the EFI ROM + // image. + // + // For H/W UNDI, this is set to zero. + + UINT32 ImageSize; + // Size of the UNrelocated driver/ROM image of this network interface. + // This is set to zero if there is no driver/ROM image. + + CHAR8 StringId[4]; + // 4 char ASCII string to go in class identifier (option 60) in DHCP + // and Boot Server discover packets. + // For EfiNetworkInterfaceUndi this field is "UNDI". + // For EfiNetworkInterfaceSnp this field is "SNPN". + + UINT8 Type; + UINT8 MajorVer; + UINT8 MinorVer; + // Information to be placed into the PXE DHCP and Discover packets. + // This is the network interface type and version number that will + // be placed into DHCP option 94 (client network interface identifier). + BOOLEAN Ipv6Supported; + UINT8 IfNum; // interface number to be used with pxeid structure +} EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL, EFI_NETWORK_INTERFACE_IDENTIFIER_INTERFACE; + +// Note: Because it conflicted with the EDK2 struct name, the +// 'EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL' GUID definition, +// from older versions of gnu-efi, is now obsoleted. +// Use 'EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL_GUID' instead. + +#endif // _EFI_NII_H diff --git a/gnu-efi/inc/efi_pxe.h b/gnu-efi/inc/efi_pxe.h new file mode 100644 index 0000000..d24251f --- /dev/null +++ b/gnu-efi/inc/efi_pxe.h @@ -0,0 +1,1743 @@ +#ifndef _EFI_PXE_H +#define _EFI_PXE_H + + +/*++ +Copyright (c) Intel 1999 + +Module name: + efi_pxe.h + +32/64-bit PXE specification: + alpha-4, 99-Dec-17 + +Abstract: + This header file contains all of the PXE type definitions, + structure prototypes, global variables and constants that + are needed for porting PXE to EFI. +--*/ + +#pragma pack(1) + +#define PXE_INTEL_ORDER 1 // Intel order +//#define PXE_NETWORK_ORDER 1 // network order + +#define PXE_UINT64_SUPPORT 1 // UINT64 supported +//#define PXE_NO_UINT64_SUPPORT 1 // UINT64 not supported + +#define PXE_BUSTYPE(a,b,c,d) \ +((((PXE_UINT32)(d) & 0xFF) << 24) | \ +(((PXE_UINT32)(c) & 0xFF) << 16) | \ +(((PXE_UINT32)(b) & 0xFF) << 8) | \ +((PXE_UINT32)(a) & 0xFF)) + +// +// UNDI ROM ID and devive ID signature +// +#define PXE_BUSTYPE_PXE PXE_BUSTYPE('!', 'P', 'X', 'E') + +// +// BUS ROM ID signatures +// +#define PXE_BUSTYPE_PCI PXE_BUSTYPE('P', 'C', 'I', 'R') +#define PXE_BUSTYPE_PC_CARD PXE_BUSTYPE('P', 'C', 'C', 'R') +#define PXE_BUSTYPE_USB PXE_BUSTYPE('U', 'S', 'B', 'R') +#define PXE_BUSTYPE_1394 PXE_BUSTYPE('1', '3', '9', '4') + +#define PXE_SWAP_UINT16(n) \ +((((PXE_UINT16)(n) & 0x00FF) << 8) | \ +(((PXE_UINT16)(n) & 0xFF00) >> 8)) + +#define PXE_SWAP_UINT32(n) \ +((((PXE_UINT32)(n) & 0x000000FF) << 24) | \ +(((PXE_UINT32)(n) & 0x0000FF00) << 8) | \ +(((PXE_UINT32)(n) & 0x00FF0000) >> 8) | \ +(((PXE_UINT32)(n) & 0xFF000000) >> 24)) + +#if PXE_UINT64_SUPPORT != 0 +#define PXE_SWAP_UINT64(n) \ +((((PXE_UINT64)(n) & 0x00000000000000FF) << 56) | \ +(((PXE_UINT64)(n) & 0x000000000000FF00) << 40) | \ +(((PXE_UINT64)(n) & 0x0000000000FF0000) << 24) | \ +(((PXE_UINT64)(n) & 0x00000000FF000000) << 8) | \ +(((PXE_UINT64)(n) & 0x000000FF00000000) >> 8) | \ +(((PXE_UINT64)(n) & 0x0000FF0000000000) >> 24) | \ +(((PXE_UINT64)(n) & 0x00FF000000000000) >> 40) | \ +(((PXE_UINT64)(n) & 0xFF00000000000000) >> 56)) +#endif // PXE_UINT64_SUPPORT + +#if PXE_NO_UINT64_SUPPORT != 0 +#define PXE_SWAP_UINT64(n) \ +{ \ +PXE_UINT32 tmp = (PXE_UINT64)(n)[1]; \ +(PXE_UINT64)(n)[1] = PXE_SWAP_UINT32((PXE_UINT64)(n)[0]); \ +(PXE_UINT64)(n)[0] = tmp; \ +} +#endif // PXE_NO_UINT64_SUPPORT + +#define PXE_CPBSIZE_NOT_USED 0 // zero +#define PXE_DBSIZE_NOT_USED 0 // zero +#define PXE_CPBADDR_NOT_USED (PXE_UINT64)0 // zero +#define PXE_DBADDR_NOT_USED (PXE_UINT64)0 // zero + +#define PXE_CONST const + +#define PXE_VOLATILE volatile + +typedef void PXE_VOID; + +typedef unsigned char PXE_UINT8; + +typedef unsigned short PXE_UINT16; + +typedef unsigned PXE_UINT32; + +#if PXE_UINT64_SUPPORT != 0 +// typedef unsigned long PXE_UINT64; +typedef UINT64 PXE_UINT64; +#endif // PXE_UINT64_SUPPORT + +#if PXE_NO_UINT64_SUPPORT != 0 +typedef PXE_UINT32 PXE_UINT64[2]; +#endif // PXE_NO_UINT64_SUPPORT + +typedef unsigned PXE_UINTN; + +typedef PXE_UINT8 PXE_BOOL; + +#define PXE_FALSE 0 // zero +#define PXE_TRUE (!PXE_FALSE) + +typedef PXE_UINT16 PXE_OPCODE; + +// +// Return UNDI operational state. +// +#define PXE_OPCODE_GET_STATE 0x0000 + +// +// Change UNDI operational state from Stopped to Started. +// +#define PXE_OPCODE_START 0x0001 + +// +// Change UNDI operational state from Started to Stopped. +// +#define PXE_OPCODE_STOP 0x0002 + +// +// Get UNDI initialization information. +// +#define PXE_OPCODE_GET_INIT_INFO 0x0003 + +// +// Get NIC configuration information. +// +#define PXE_OPCODE_GET_CONFIG_INFO 0x0004 + +// +// Changed UNDI operational state from Started to Initialized. +// +#define PXE_OPCODE_INITIALIZE 0x0005 + +// +// Re-initialize the NIC H/W. +// +#define PXE_OPCODE_RESET 0x0006 + +// +// Change the UNDI operational state from Initialized to Started. +// +#define PXE_OPCODE_SHUTDOWN 0x0007 + +// +// Read & change state of external interrupt enables. +// +#define PXE_OPCODE_INTERRUPT_ENABLES 0x0008 + +// +// Read & change state of packet receive filters. +// +#define PXE_OPCODE_RECEIVE_FILTERS 0x0009 + +// +// Read & change station MAC address. +// +#define PXE_OPCODE_STATION_ADDRESS 0x000A + +// +// Read traffic statistics. +// +#define PXE_OPCODE_STATISTICS 0x000B + +// +// Convert multicast IP address to multicast MAC address. +// +#define PXE_OPCODE_MCAST_IP_TO_MAC 0x000C + +// +// Read or change non-volatile storage on the NIC. +// +#define PXE_OPCODE_NVDATA 0x000D + +// +// Get & clear interrupt status. +// +#define PXE_OPCODE_GET_STATUS 0x000E + +// +// Fill media header in packet for transmit. +// +#define PXE_OPCODE_FILL_HEADER 0x000F + +// +// Transmit packet(s). +// +#define PXE_OPCODE_TRANSMIT 0x0010 + +// +// Receive packet. +// +#define PXE_OPCODE_RECEIVE 0x0011 + +// last valid opcode: +#define PXE_OPCODE_VALID_MAX 0x0011 + +// +// Last valid PXE UNDI OpCode number. +// +#define PXE_OPCODE_LAST_VALID 0x0011 + +typedef PXE_UINT16 PXE_OPFLAGS; + +#define PXE_OPFLAGS_NOT_USED 0x0000 + +//////////////////////////////////////// +// UNDI Get State +// + +// No OpFlags + +//////////////////////////////////////// +// UNDI Start +// + +// No OpFlags + +//////////////////////////////////////// +// UNDI Stop +// + +// No OpFlags + +//////////////////////////////////////// +// UNDI Get Init Info +// + +// No Opflags + +//////////////////////////////////////// +// UNDI Get Config Info +// + +// No Opflags + +//////////////////////////////////////// +// UNDI Initialize +// + +#define PXE_OPFLAGS_INITIALIZE_CABLE_DETECT_MASK 0x0001 +#define PXE_OPFLAGS_INITIALIZE_DETECT_CABLE 0x0000 +#define PXE_OPFLAGS_INITIALIZE_DO_NOT_DETECT_CABLE 0x0001 + +//////////////////////////////////////// +// UNDI Reset +// + +#define PXE_OPFLAGS_RESET_DISABLE_INTERRUPTS 0x0001 +#define PXE_OPFLAGS_RESET_DISABLE_FILTERS 0x0002 + +//////////////////////////////////////// +// UNDI Shutdown +// + +// No OpFlags + +//////////////////////////////////////// +// UNDI Interrupt Enables +// + +// +// Select whether to enable or disable external interrupt signals. +// Setting both enable and disable will return PXE_STATCODE_INVALID_OPFLAGS. +// +#define PXE_OPFLAGS_INTERRUPT_OPMASK 0xC000 +#define PXE_OPFLAGS_INTERRUPT_ENABLE 0x8000 +#define PXE_OPFLAGS_INTERRUPT_DISABLE 0x4000 +#define PXE_OPFLAGS_INTERRUPT_READ 0x0000 + +// +// Enable receive interrupts. An external interrupt will be generated +// after a complete non-error packet has been received. +// +#define PXE_OPFLAGS_INTERRUPT_RECEIVE 0x0001 + +// +// Enable transmit interrupts. An external interrupt will be generated +// after a complete non-error packet has been transmitted. +// +#define PXE_OPFLAGS_INTERRUPT_TRANSMIT 0x0002 + +// +// Enable command interrupts. An external interrupt will be generated +// when command execution stops. +// +#define PXE_OPFLAGS_INTERRUPT_COMMAND 0x0004 + +// +// Generate software interrupt. Setting this bit generates an external +// interrupt, if it is supported by the hardware. +// +#define PXE_OPFLAGS_INTERRUPT_SOFTWARE 0x0008 + +//////////////////////////////////////// +// UNDI Receive Filters +// + +// +// Select whether to enable or disable receive filters. +// Setting both enable and disable will return PXE_STATCODE_INVALID_OPCODE. +// +#define PXE_OPFLAGS_RECEIVE_FILTER_OPMASK 0xC000 +#define PXE_OPFLAGS_RECEIVE_FILTER_ENABLE 0x8000 +#define PXE_OPFLAGS_RECEIVE_FILTER_DISABLE 0x4000 +#define PXE_OPFLAGS_RECEIVE_FILTER_READ 0x0000 + +// +// To reset the contents of the multicast MAC address filter list, +// set this OpFlag: +// +#define PXE_OPFLAGS_RECEIVE_FILTER_RESET_MCAST_LIST 0x2000 + +// +// Enable unicast packet receiving. Packets sent to the current station +// MAC address will be received. +// +#define PXE_OPFLAGS_RECEIVE_FILTER_UNICAST 0x0001 + +// +// Enable broadcast packet receiving. Packets sent to the broadcast +// MAC address will be received. +// +#define PXE_OPFLAGS_RECEIVE_FILTER_BROADCAST 0x0002 + +// +// Enable filtered multicast packet receiving. Packets sent to any +// of the multicast MAC addresses in the multicast MAC address filter +// list will be received. If the filter list is empty, no multicast +// +#define PXE_OPFLAGS_RECEIVE_FILTER_FILTERED_MULTICAST 0x0004 + +// +// Enable promiscuous packet receiving. All packets will be received. +// +#define PXE_OPFLAGS_RECEIVE_FILTER_PROMISCUOUS 0x0008 + +// +// Enable promiscuous multicast packet receiving. All multicast +// packets will be received. +// +#define PXE_OPFLAGS_RECEIVE_FILTER_ALL_MULTICAST 0x0010 + +//////////////////////////////////////// +// UNDI Station Address +// + +#define PXE_OPFLAGS_STATION_ADDRESS_READ 0x0000 +#define PXE_OPFLAGS_STATION_ADDRESS_RESET 0x0001 + +//////////////////////////////////////// +// UNDI Statistics +// + +#define PXE_OPFLAGS_STATISTICS_READ 0x0000 +#define PXE_OPFLAGS_STATISTICS_RESET 0x0001 + +//////////////////////////////////////// +// UNDI MCast IP to MAC +// + +// +// Identify the type of IP address in the CPB. +// +#define PXE_OPFLAGS_MCAST_IP_TO_MAC_OPMASK 0x0003 +#define PXE_OPFLAGS_MCAST_IPV4_TO_MAC 0x0000 +#define PXE_OPFLAGS_MCAST_IPV6_TO_MAC 0x0001 + +//////////////////////////////////////// +// UNDI NvData +// + +// +// Select the type of non-volatile data operation. +// +#define PXE_OPFLAGS_NVDATA_OPMASK 0x0001 +#define PXE_OPFLAGS_NVDATA_READ 0x0000 +#define PXE_OPFLAGS_NVDATA_WRITE 0x0001 + +//////////////////////////////////////// +// UNDI Get Status +// + +// +// Return current interrupt status. This will also clear any interrupts +// that are currently set. This can be used in a polling routine. The +// interrupt flags are still set and cleared even when the interrupts +// are disabled. +// +#define PXE_OPFLAGS_GET_INTERRUPT_STATUS 0x0001 + +// +// Return list of transmitted buffers for recycling. Transmit buffers +// must not be changed or unallocated until they have recycled. After +// issuing a transmit command, wait for a transmit complete interrupt. +// When a transmit complete interrupt is received, read the transmitted +// buffers. Do not plan on getting one buffer per interrupt. Some +// NICs and UNDIs may transmit multiple buffers per interrupt. +// +#define PXE_OPFLAGS_GET_TRANSMITTED_BUFFERS 0x0002 + +//////////////////////////////////////// +// UNDI Fill Header +// + +#define PXE_OPFLAGS_FILL_HEADER_OPMASK 0x0001 +#define PXE_OPFLAGS_FILL_HEADER_FRAGMENTED 0x0001 +#define PXE_OPFLAGS_FILL_HEADER_WHOLE 0x0000 + +//////////////////////////////////////// +// UNDI Transmit +// + +// +// S/W UNDI only. Return after the packet has been transmitted. A +// transmit complete interrupt will still be generated and the transmit +// buffer will have to be recycled. +// +#define PXE_OPFLAGS_SWUNDI_TRANSMIT_OPMASK 0x0001 +#define PXE_OPFLAGS_TRANSMIT_BLOCK 0x0001 +#define PXE_OPFLAGS_TRANSMIT_DONT_BLOCK 0x0000 + +// +// +// +#define PXE_OPFLAGS_TRANSMIT_OPMASK 0x0002 +#define PXE_OPFLAGS_TRANSMIT_FRAGMENTED 0x0002 +#define PXE_OPFLAGS_TRANSMIT_WHOLE 0x0000 + +//////////////////////////////////////// +// UNDI Receive +// + +// No OpFlags + +typedef PXE_UINT16 PXE_STATFLAGS; + +#define PXE_STATFLAGS_INITIALIZE 0x0000 + +//////////////////////////////////////// +// Common StatFlags that can be returned by all commands. +// + +// +// The COMMAND_COMPLETE and COMMAND_FAILED status flags must be +// implemented by all UNDIs. COMMAND_QUEUED is only needed by UNDIs +// that support command queuing. +// +#define PXE_STATFLAGS_STATUS_MASK 0xC000 +#define PXE_STATFLAGS_COMMAND_COMPLETE 0xC000 +#define PXE_STATFLAGS_COMMAND_FAILED 0x8000 +#define PXE_STATFLAGS_COMMAND_QUEUED 0x4000 +//#define PXE_STATFLAGS_INITIALIZE 0x0000 + +#define PXE_STATFLAGS_DB_WRITE_TRUNCATED 0x2000 + +//////////////////////////////////////// +// UNDI Get State +// + +#define PXE_STATFLAGS_GET_STATE_MASK 0x0003 +#define PXE_STATFLAGS_GET_STATE_INITIALIZED 0x0002 +#define PXE_STATFLAGS_GET_STATE_STARTED 0x0001 +#define PXE_STATFLAGS_GET_STATE_STOPPED 0x0000 + +//////////////////////////////////////// +// UNDI Start +// + +// No additional StatFlags + +//////////////////////////////////////// +// UNDI Get Init Info +// + +#define PXE_STATFLAGS_CABLE_DETECT_MASK 0x0001 +#define PXE_STATFLAGS_CABLE_DETECT_NOT_SUPPORTED 0x0000 +#define PXE_STATFLAGS_CABLE_DETECT_SUPPORTED 0x0001 + + +//////////////////////////////////////// +// UNDI Initialize +// + +#define PXE_STATFLAGS_INITIALIZED_NO_MEDIA 0x0001 + +//////////////////////////////////////// +// UNDI Reset +// + +#define PXE_STATFLAGS_RESET_NO_MEDIA 0x0001 + +//////////////////////////////////////// +// UNDI Shutdown +// + +// No additional StatFlags + +//////////////////////////////////////// +// UNDI Interrupt Enables +// + +// +// If set, receive interrupts are enabled. +// +#define PXE_STATFLAGS_INTERRUPT_RECEIVE 0x0001 + +// +// If set, transmit interrupts are enabled. +// +#define PXE_STATFLAGS_INTERRUPT_TRANSMIT 0x0002 + +// +// If set, command interrupts are enabled. +// +#define PXE_STATFLAGS_INTERRUPT_COMMAND 0x0004 + + +//////////////////////////////////////// +// UNDI Receive Filters +// + +// +// If set, unicast packets will be received. +// +#define PXE_STATFLAGS_RECEIVE_FILTER_UNICAST 0x0001 + +// +// If set, broadcast packets will be received. +// +#define PXE_STATFLAGS_RECEIVE_FILTER_BROADCAST 0x0002 + +// +// If set, multicast packets that match up with the multicast address +// filter list will be received. +// +#define PXE_STATFLAGS_RECEIVE_FILTER_FILTERED_MULTICAST 0x0004 + +// +// If set, all packets will be received. +// +#define PXE_STATFLAGS_RECEIVE_FILTER_PROMISCUOUS 0x0008 + +// +// If set, all multicast packets will be received. +// +#define PXE_STATFLAGS_RECEIVE_FILTER_ALL_MULTICAST 0x0010 + +//////////////////////////////////////// +// UNDI Station Address +// + +// No additional StatFlags + +//////////////////////////////////////// +// UNDI Statistics +// + +// No additional StatFlags + +//////////////////////////////////////// +// UNDI MCast IP to MAC +// + +// No additional StatFlags + +//////////////////////////////////////// +// UNDI NvData +// + +// No additional StatFlags + + +//////////////////////////////////////// +// UNDI Get Status +// + +// +// Use to determine if an interrupt has occurred. +// +#define PXE_STATFLAGS_GET_STATUS_INTERRUPT_MASK 0x000F +#define PXE_STATFLAGS_GET_STATUS_NO_INTERRUPTS 0x0000 + +// +// If set, at least one receive interrupt occurred. +// +#define PXE_STATFLAGS_GET_STATUS_RECEIVE 0x0001 + +// +// If set, at least one transmit interrupt occurred. +// +#define PXE_STATFLAGS_GET_STATUS_TRANSMIT 0x0002 + +// +// If set, at least one command interrupt occurred. +// +#define PXE_STATFLAGS_GET_STATUS_COMMAND 0x0004 + +// +// If set, at least one software interrupt occurred. +// +#define PXE_STATFLAGS_GET_STATUS_SOFTWARE 0x0008 + +// +// This flag is set if the transmitted buffer queue is empty. This flag +// will be set if all transmitted buffer addresses get written into the DB. +// +#define PXE_STATFLAGS_GET_STATUS_TXBUF_QUEUE_EMPTY 0x0010 + +// +// This flag is set if no transmitted buffer addresses were written +// into the DB. (This could be because DBsize was too small.) +// +#define PXE_STATFLAGS_GET_STATUS_NO_TXBUFS_WRITTEN 0x0020 + +//////////////////////////////////////// +// UNDI Fill Header +// + +// No additional StatFlags + +//////////////////////////////////////// +// UNDI Transmit +// + +// No additional StatFlags. + +//////////////////////////////////////// +// UNDI Receive +// + +// No additional StatFlags. + +typedef PXE_UINT16 PXE_STATCODE; + +#define PXE_STATCODE_INITIALIZE 0x0000 + +//////////////////////////////////////// +// Common StatCodes returned by all UNDI commands, UNDI protocol functions +// and BC protocol functions. +// + +#define PXE_STATCODE_SUCCESS 0x0000 + +#define PXE_STATCODE_INVALID_CDB 0x0001 +#define PXE_STATCODE_INVALID_CPB 0x0002 +#define PXE_STATCODE_BUSY 0x0003 +#define PXE_STATCODE_QUEUE_FULL 0x0004 +#define PXE_STATCODE_ALREADY_STARTED 0x0005 +#define PXE_STATCODE_NOT_STARTED 0x0006 +#define PXE_STATCODE_NOT_SHUTDOWN 0x0007 +#define PXE_STATCODE_ALREADY_INITIALIZED 0x0008 +#define PXE_STATCODE_NOT_INITIALIZED 0x0009 +#define PXE_STATCODE_DEVICE_FAILURE 0x000A +#define PXE_STATCODE_NVDATA_FAILURE 0x000B +#define PXE_STATCODE_UNSUPPORTED 0x000C +#define PXE_STATCODE_BUFFER_FULL 0x000D +#define PXE_STATCODE_INVALID_PARAMETER 0x000E +#define PXE_STATCODE_INVALID_UNDI 0x000F +#define PXE_STATCODE_IPV4_NOT_SUPPORTED 0x0010 +#define PXE_STATCODE_IPV6_NOT_SUPPORTED 0x0011 +#define PXE_STATCODE_NOT_ENOUGH_MEMORY 0x0012 +#define PXE_STATCODE_NO_DATA 0x0013 + + +typedef PXE_UINT16 PXE_IFNUM; + +// +// This interface number must be passed to the S/W UNDI Start command. +// +#define PXE_IFNUM_START 0x0000 + +// +// This interface number is returned by the S/W UNDI Get State and +// Start commands if information in the CDB, CPB or DB is invalid. +// +#define PXE_IFNUM_INVALID 0x0000 + +typedef PXE_UINT16 PXE_CONTROL; + +// +// Setting this flag directs the UNDI to queue this command for later +// execution if the UNDI is busy and it supports command queuing. +// If queuing is not supported, a PXE_STATCODE_INVALID_CONTROL error +// is returned. If the queue is full, a PXE_STATCODE_CDB_QUEUE_FULL +// error is returned. +// +#define PXE_CONTROL_QUEUE_IF_BUSY 0x0002 + +// +// These two bit values are used to determine if there are more UNDI +// CDB structures following this one. If the link bit is set, there +// must be a CDB structure following this one. Execution will start +// on the next CDB structure as soon as this one completes successfully. +// If an error is generated by this command, execution will stop. +// +#define PXE_CONTROL_LINK 0x0001 +#define PXE_CONTROL_LAST_CDB_IN_LIST 0x0000 + +typedef PXE_UINT8 PXE_FRAME_TYPE; + +#define PXE_FRAME_TYPE_NONE 0x00 +#define PXE_FRAME_TYPE_UNICAST 0x01 +#define PXE_FRAME_TYPE_BROADCAST 0x02 +#define PXE_FRAME_TYPE_MULTICAST 0x03 +#define PXE_FRAME_TYPE_PROMISCUOUS 0x04 + +typedef PXE_UINT32 PXE_IPV4; + +typedef PXE_UINT32 PXE_IPV6[4]; +#define PXE_MAC_LENGTH 32 + +typedef PXE_UINT8 PXE_MAC_ADDR[PXE_MAC_LENGTH]; + +typedef PXE_UINT8 PXE_IFTYPE; +typedef PXE_UINT16 PXE_MEDIA_PROTOCOL; + +// +// This information is from the ARP section of RFC 1700. +// +// 1 Ethernet (10Mb) [JBP] +// 2 Experimental Ethernet (3Mb) [JBP] +// 3 Amateur Radio AX.25 [PXK] +// 4 Proteon ProNET Token Ring [JBP] +// 5 Chaos [GXP] +// 6 IEEE 802 Networks [JBP] +// 7 ARCNET [JBP] +// 8 Hyperchannel [JBP] +// 9 Lanstar [TU] +// 10 Autonet Short Address [MXB1] +// 11 LocalTalk [JKR1] +// 12 LocalNet (IBM PCNet or SYTEK LocalNET) [JXM] +// 13 Ultra link [RXD2] +// 14 SMDS [GXC1] +// 15 Frame Relay [AGM] +// 16 Asynchronous Transmission Mode (ATM) [JXB2] +// 17 HDLC [JBP] +// 18 Fibre Channel [Yakov Rekhter] +// 19 Asynchronous Transmission Mode (ATM) [Mark Laubach] +// 20 Serial Line [JBP] +// 21 Asynchronous Transmission Mode (ATM) [MXB1] +// + +#define PXE_IFTYPE_ETHERNET 0x01 +#define PXE_IFTYPE_TOKENRING 0x04 +#define PXE_IFTYPE_FIBRE_CHANNEL 0x12 + +typedef struct s_pxe_hw_undi { +PXE_UINT32 Signature; // PXE_ROMID_SIGNATURE +PXE_UINT8 Len; // sizeof(PXE_HW_UNDI) +PXE_UINT8 Fudge; // makes 8-bit cksum equal zero +PXE_UINT8 Rev; // PXE_ROMID_REV +PXE_UINT8 IFcnt; // physical connector count +PXE_UINT8 MajorVer; // PXE_ROMID_MAJORVER +PXE_UINT8 MinorVer; // PXE_ROMID_MINORVER +PXE_UINT16 reserved; // zero, not used +PXE_UINT32 Implementation; // implementation flags +// reserved // vendor use +// PXE_UINT32 Status; // status port +// PXE_UINT32 Command; // command port +// PXE_UINT64 CDBaddr; // CDB address port +} PXE_HW_UNDI; + +// +// Status port bit definitions +// + +// +// UNDI operation state +// +#define PXE_HWSTAT_STATE_MASK 0xC0000000 +#define PXE_HWSTAT_BUSY 0xC0000000 +#define PXE_HWSTAT_INITIALIZED 0x80000000 +#define PXE_HWSTAT_STARTED 0x40000000 +#define PXE_HWSTAT_STOPPED 0x00000000 + +// +// If set, last command failed +// +#define PXE_HWSTAT_COMMAND_FAILED 0x20000000 + +// +// If set, identifies enabled receive filters +// +#define PXE_HWSTAT_PROMISCUOUS_MULTICAST_RX_ENABLED 0x00001000 +#define PXE_HWSTAT_PROMISCUOUS_RX_ENABLED 0x00000800 +#define PXE_HWSTAT_BROADCAST_RX_ENABLED 0x00000400 +#define PXE_HWSTAT_MULTICAST_RX_ENABLED 0x00000200 +#define PXE_HWSTAT_UNICAST_RX_ENABLED 0x00000100 + +// +// If set, identifies enabled external interrupts +// +#define PXE_HWSTAT_SOFTWARE_INT_ENABLED 0x00000080 +#define PXE_HWSTAT_TX_COMPLETE_INT_ENABLED 0x00000040 +#define PXE_HWSTAT_PACKET_RX_INT_ENABLED 0x00000020 +#define PXE_HWSTAT_CMD_COMPLETE_INT_ENABLED 0x00000010 + +// +// If set, identifies pending interrupts +// +#define PXE_HWSTAT_SOFTWARE_INT_PENDING 0x00000008 +#define PXE_HWSTAT_TX_COMPLETE_INT_PENDING 0x00000004 +#define PXE_HWSTAT_PACKET_RX_INT_PENDING 0x00000002 +#define PXE_HWSTAT_CMD_COMPLETE_INT_PENDING 0x00000001 + +// +// Command port definitions +// + +// +// If set, CDB identified in CDBaddr port is given to UNDI. +// If not set, other bits in this word will be processed. +// +#define PXE_HWCMD_ISSUE_COMMAND 0x80000000 +#define PXE_HWCMD_INTS_AND_FILTS 0x00000000 + +// +// Use these to enable/disable receive filters. +// +#define PXE_HWCMD_PROMISCUOUS_MULTICAST_RX_ENABLE 0x00001000 +#define PXE_HWCMD_PROMISCUOUS_RX_ENABLE 0x00000800 +#define PXE_HWCMD_BROADCAST_RX_ENABLE 0x00000400 +#define PXE_HWCMD_MULTICAST_RX_ENABLE 0x00000200 +#define PXE_HWCMD_UNICAST_RX_ENABLE 0x00000100 + +// +// Use these to enable/disable external interrupts +// +#define PXE_HWCMD_SOFTWARE_INT_ENABLE 0x00000080 +#define PXE_HWCMD_TX_COMPLETE_INT_ENABLE 0x00000040 +#define PXE_HWCMD_PACKET_RX_INT_ENABLE 0x00000020 +#define PXE_HWCMD_CMD_COMPLETE_INT_ENABLE 0x00000010 + +// +// Use these to clear pending external interrupts +// +#define PXE_HWCMD_CLEAR_SOFTWARE_INT 0x00000008 +#define PXE_HWCMD_CLEAR_TX_COMPLETE_INT 0x00000004 +#define PXE_HWCMD_CLEAR_PACKET_RX_INT 0x00000002 +#define PXE_HWCMD_CLEAR_CMD_COMPLETE_INT 0x00000001 + +typedef struct s_pxe_sw_undi { +PXE_UINT32 Signature; // PXE_ROMID_SIGNATURE +PXE_UINT8 Len; // sizeof(PXE_SW_UNDI) +PXE_UINT8 Fudge; // makes 8-bit cksum zero +PXE_UINT8 Rev; // PXE_ROMID_REV +PXE_UINT8 IFcnt; // physical connector count +PXE_UINT8 MajorVer; // PXE_ROMID_MAJORVER +PXE_UINT8 MinorVer; // PXE_ROMID_MINORVER +PXE_UINT16 reserved1; // zero, not used +PXE_UINT32 Implementation; // Implementation flags +PXE_UINT64 EntryPoint; // API entry point +PXE_UINT8 reserved2[3]; // zero, not used +PXE_UINT8 BusCnt; // number of bustypes supported +PXE_UINT32 BusType[1]; // list of supported bustypes +} PXE_SW_UNDI; + +typedef union u_pxe_undi { +PXE_HW_UNDI hw; +PXE_SW_UNDI sw; +} PXE_UNDI; + +// +// Signature of !PXE structure +// +#define PXE_ROMID_SIGNATURE PXE_BUSTYPE('!', 'P', 'X', 'E') + +// +// !PXE structure format revision +// +#define PXE_ROMID_REV 0x02 + +// +// UNDI command interface revision. These are the values that get sent +// in option 94 (Client Network Interface Identifier) in the DHCP Discover +// and PXE Boot Server Request packets. +// +#define PXE_ROMID_MAJORVER 0x03 +#define PXE_ROMID_MINORVER 0x00 + +// +// Implementation flags +// +#define PXE_ROMID_IMP_HW_UNDI 0x80000000 +#define PXE_ROMID_IMP_SW_VIRT_ADDR 0x40000000 +#define PXE_ROMID_IMP_64BIT_DEVICE 0x00010000 +#define PXE_ROMID_IMP_FRAG_SUPPORTED 0x00008000 +#define PXE_ROMID_IMP_CMD_LINK_SUPPORTED 0x00004000 +#define PXE_ROMID_IMP_CMD_QUEUE_SUPPORTED 0x00002000 +#define PXE_ROMID_IMP_MULTI_FRAME_SUPPORTED 0x00001000 +#define PXE_ROMID_IMP_NVDATA_SUPPORT_MASK 0x00000C00 +#define PXE_ROMID_IMP_NVDATA_BULK_WRITABLE 0x00000C00 +#define PXE_ROMID_IMP_NVDATA_SPARSE_WRITABLE 0x00000800 +#define PXE_ROMID_IMP_NVDATA_READ_ONLY 0x00000400 +#define PXE_ROMID_IMP_NVDATA_NOT_AVAILABLE 0x00000000 +#define PXE_ROMID_IMP_STATISTICS_SUPPORTED 0x00000200 +#define PXE_ROMID_IMP_STATION_ADDR_SETTABLE 0x00000100 +#define PXE_ROMID_IMP_PROMISCUOUS_MULTICAST_RX_SUPPORTED 0x00000080 +#define PXE_ROMID_IMP_PROMISCUOUS_RX_SUPPORTED 0x00000040 +#define PXE_ROMID_IMP_BROADCAST_RX_SUPPORTED 0x00000020 +#define PXE_ROMID_IMP_FILTERED_MULTICAST_RX_SUPPORTED 0x00000010 +#define PXE_ROMID_IMP_SOFTWARE_INT_SUPPORTED 0x00000008 +#define PXE_ROMID_IMP_TX_COMPLETE_INT_SUPPORTED 0x00000004 +#define PXE_ROMID_IMP_PACKET_RX_INT_SUPPORTED 0x00000002 +#define PXE_ROMID_IMP_CMD_COMPLETE_INT_SUPPORTED 0x00000001 + + +typedef struct s_pxe_cdb { +PXE_OPCODE OpCode; +PXE_OPFLAGS OpFlags; +PXE_UINT16 CPBsize; +PXE_UINT16 DBsize; +UINT64 CPBaddr; +UINT64 DBaddr; +PXE_STATCODE StatCode; +PXE_STATFLAGS StatFlags; +PXE_UINT16 IFnum; +PXE_CONTROL Control; +} PXE_CDB; + + +typedef union u_pxe_ip_addr { +PXE_IPV6 IPv6; +PXE_IPV4 IPv4; +} PXE_IP_ADDR; + +typedef union pxe_device { +// +// PCI and PC Card NICs are both identified using bus, device +// and function numbers. For PC Card, this may require PC +// Card services to be loaded in the BIOS or preboot +// environment. +// +struct { +// +// See S/W UNDI ROMID structure definition for PCI and +// PCC BusType definitions. +// +PXE_UINT32 BusType; + +// +// Bus, device & function numbers that locate this device. +// +PXE_UINT16 Bus; +PXE_UINT8 Device; +PXE_UINT8 Function; +} PCI, PCC; + +// +// %%TBD - More information is needed about enumerating +// USB and 1394 devices. +// +struct { +PXE_UINT32 BusType; +PXE_UINT32 tdb; +} USB, _1394; +} PXE_DEVICE; + +// cpb and db definitions + +#define MAX_PCI_CONFIG_LEN 64 // # of dwords +#define MAX_EEPROM_LEN 128 // #of dwords +#define MAX_XMIT_BUFFERS 32 // recycling Q length for xmit_done +#define MAX_MCAST_ADDRESS_CNT 8 + +typedef struct s_pxe_cpb_start { + // + // PXE_VOID Delay(PXE_UINT64 microseconds); + // + // UNDI will never request a delay smaller than 10 microseconds + // and will always request delays in increments of 10 microseconds. + // The Delay() CallBack routine must delay between n and n + 10 + // microseconds before returning control to the UNDI. + // + // This field cannot be set to zero. + // + PXE_UINT64 Delay; + + // + // PXE_VOID Block(PXE_UINT32 enable); + // + // UNDI may need to block multi-threaded/multi-processor access to + // critical code sections when programming or accessing the network + // device. To this end, a blocking service is needed by the UNDI. + // When UNDI needs a block, it will call Block() passing a non-zero + // value. When UNDI no longer needs a block, it will call Block() + // with a zero value. When called, if the Block() is already enabled, + // do not return control to the UNDI until the previous Block() is + // disabled. + // + // This field cannot be set to zero. + // + PXE_UINT64 Block; + + // + // PXE_VOID Virt2Phys(PXE_UINT64 virtual, PXE_UINT64 physical_ptr); + // + // UNDI will pass the virtual address of a buffer and the virtual + // address of a 64-bit physical buffer. Convert the virtual address + // to a physical address and write the result to the physical address + // buffer. If virtual and physical addresses are the same, just + // copy the virtual address to the physical address buffer. + // + // This field can be set to zero if virtual and physical addresses + // are equal. + // + PXE_UINT64 Virt2Phys; + // + // PXE_VOID Mem_IO(PXE_UINT8 read_write, PXE_UINT8 len, PXE_UINT64 port, + // PXE_UINT64 buf_addr); + // + // UNDI will read or write the device io space using this call back + // function. It passes the number of bytes as the len parameter and it + // will be either 1,2,4 or 8. + // + // This field can not be set to zero. + // + PXE_UINT64 Mem_IO; +} PXE_CPB_START; + +#define PXE_DELAY_MILLISECOND 1000 +#define PXE_DELAY_SECOND 1000000 +#define PXE_IO_READ 0 +#define PXE_IO_WRITE 1 +#define PXE_MEM_READ 2 +#define PXE_MEM_WRITE 4 + + +typedef struct s_pxe_db_get_init_info { + // + // Minimum length of locked memory buffer that must be given to + // the Initialize command. Giving UNDI more memory will generally + // give better performance. + // + // If MemoryRequired is zero, the UNDI does not need and will not + // use system memory to receive and transmit packets. + // + PXE_UINT32 MemoryRequired; + + // + // Maximum frame data length for Tx/Rx excluding the media header. + // + PXE_UINT32 FrameDataLen; + + // + // Supported link speeds are in units of mega bits. Common ethernet + // values are 10, 100 and 1000. Unused LinkSpeeds[] entries are zero + // filled. + // + PXE_UINT32 LinkSpeeds[4]; + + // + // Number of non-volatile storage items. + // + PXE_UINT32 NvCount; + + // + // Width of non-volatile storage item in bytes. 0, 1, 2 or 4 + // + PXE_UINT16 NvWidth; + + // + // Media header length. This is the typical media header length for + // this UNDI. This information is needed when allocating receive + // and transmit buffers. + // + PXE_UINT16 MediaHeaderLen; + + // + // Number of bytes in the NIC hardware (MAC) address. + // + PXE_UINT16 HWaddrLen; + + // + // Maximum number of multicast MAC addresses in the multicast + // MAC address filter list. + // + PXE_UINT16 MCastFilterCnt; + + // + // Default number and size of transmit and receive buffers that will + // be allocated by the UNDI. If MemoryRequired is non-zero, this + // allocation will come out of the memory buffer given to the Initialize + // command. If MemoryRequired is zero, this allocation will come out of + // memory on the NIC. + // + PXE_UINT16 TxBufCnt; + PXE_UINT16 TxBufSize; + PXE_UINT16 RxBufCnt; + PXE_UINT16 RxBufSize; + + // + // Hardware interface types defined in the Assigned Numbers RFC + // and used in DHCP and ARP packets. + // See the PXE_IFTYPE typedef and PXE_IFTYPE_xxx macros. + // + PXE_UINT8 IFtype; + + // + // Supported duplex. See PXE_DUPLEX_xxxxx #defines below. + // + PXE_UINT8 Duplex; + + // + // Supported loopback options. See PXE_LOOPBACK_xxxxx #defines below. + // + PXE_UINT8 LoopBack; +} PXE_DB_GET_INIT_INFO; + +#define PXE_MAX_TXRX_UNIT_ETHER 1500 + +#define PXE_HWADDR_LEN_ETHER 0x0006 +#define PXE_MAC_HEADER_LEN_ETHER 0x000E + +#define PXE_DUPLEX_ENABLE_FULL_SUPPORTED 1 +#define PXE_DUPLEX_FORCE_FULL_SUPPORTED 2 + +#define PXE_LOOPBACK_INTERNAL_SUPPORTED 1 +#define PXE_LOOPBACK_EXTERNAL_SUPPORTED 2 + + +typedef struct s_pxe_pci_config_info { + // + // This is the flag field for the PXE_DB_GET_CONFIG_INFO union. + // For PCI bus devices, this field is set to PXE_BUSTYPE_PCI. + // + PXE_UINT32 BusType; + + // + // This identifies the PCI network device that this UNDI interface + // is bound to. + // + PXE_UINT16 Bus; + PXE_UINT8 Device; + PXE_UINT8 Function; + + // + // This is a copy of the PCI configuration space for this + // network device. + // + union { + PXE_UINT8 Byte[256]; + PXE_UINT16 Word[128]; + PXE_UINT32 Dword[64]; + } Config; +} PXE_PCI_CONFIG_INFO; + + +typedef struct s_pxe_pcc_config_info { + // + // This is the flag field for the PXE_DB_GET_CONFIG_INFO union. + // For PCC bus devices, this field is set to PXE_BUSTYPE_PCC. + // + PXE_UINT32 BusType; + + // + // This identifies the PCC network device that this UNDI interface + // is bound to. + // + PXE_UINT16 Bus; + PXE_UINT8 Device; + PXE_UINT8 Function; + + // + // This is a copy of the PCC configuration space for this + // network device. + // + union { + PXE_UINT8 Byte[256]; + PXE_UINT16 Word[128]; + PXE_UINT32 Dword[64]; + } Config; +} PXE_PCC_CONFIG_INFO; + + +typedef struct s_pxe_usb_config_info { + PXE_UINT32 BusType; + // %%TBD What should we return here... +} PXE_USB_CONFIG_INFO; + + +typedef struct s_pxe_1394_config_info { + PXE_UINT32 BusType; + // %%TBD What should we return here... +} PXE_1394_CONFIG_INFO; + + +typedef union u_pxe_db_get_config_info { + PXE_PCI_CONFIG_INFO pci; + PXE_PCC_CONFIG_INFO pcc; + PXE_USB_CONFIG_INFO usb; + PXE_1394_CONFIG_INFO _1394; +} PXE_DB_GET_CONFIG_INFO; + + +typedef struct s_pxe_cpb_initialize { + // + // Address of first (lowest) byte of the memory buffer. This buffer must + // be in contiguous physical memory and cannot be swapped out. The UNDI + // will be using this for transmit and receive buffering. + // + PXE_UINT64 MemoryAddr; + + // + // MemoryLength must be greater than or equal to MemoryRequired + // returned by the Get Init Info command. + // + PXE_UINT32 MemoryLength; + + // + // Desired link speed in Mbit/sec. Common ethernet values are 10, 100 + // and 1000. Setting a value of zero will auto-detect and/or use the + // default link speed (operation depends on UNDI/NIC functionality). + // + PXE_UINT32 LinkSpeed; + + // + // Suggested number and size of receive and transmit buffers to + // allocate. If MemoryAddr and MemoryLength are non-zero, this + // allocation comes out of the supplied memory buffer. If MemoryAddr + // and MemoryLength are zero, this allocation comes out of memory + // on the NIC. + // + // If these fields are set to zero, the UNDI will allocate buffer + // counts and sizes as it sees fit. + // + PXE_UINT16 TxBufCnt; + PXE_UINT16 TxBufSize; + PXE_UINT16 RxBufCnt; + PXE_UINT16 RxBufSize; + + // + // The following configuration parameters are optional and must be zero + // to use the default values. + // + PXE_UINT8 Duplex; + + PXE_UINT8 LoopBack; +} PXE_CPB_INITIALIZE; + + +#define PXE_DUPLEX_DEFAULT 0x00 +#define PXE_FORCE_FULL_DUPLEX 0x01 +#define PXE_ENABLE_FULL_DUPLEX 0x02 + +#define LOOPBACK_NORMAL 0 +#define LOOPBACK_INTERNAL 1 +#define LOOPBACK_EXTERNAL 2 + + +typedef struct s_pxe_db_initialize { + // + // Actual amount of memory used from the supplied memory buffer. This + // may be less that the amount of memory suppllied and may be zero if + // the UNDI and network device do not use external memory buffers. + // + // Memory used by the UNDI and network device is allocated from the + // lowest memory buffer address. + // + PXE_UINT32 MemoryUsed; + + // + // Actual number and size of receive and transmit buffers that were + // allocated. + // + PXE_UINT16 TxBufCnt; + PXE_UINT16 TxBufSize; + PXE_UINT16 RxBufCnt; + PXE_UINT16 RxBufSize; +} PXE_DB_INITIALIZE; + + +typedef struct s_pxe_cpb_receive_filters { + // + // List of multicast MAC addresses. This list, if present, will + // replace the existing multicast MAC address filter list. + // + PXE_MAC_ADDR MCastList[MAX_MCAST_ADDRESS_CNT]; +} PXE_CPB_RECEIVE_FILTERS; + + +typedef struct s_pxe_db_receive_filters { + // + // Filtered multicast MAC address list. + // + PXE_MAC_ADDR MCastList[MAX_MCAST_ADDRESS_CNT]; +} PXE_DB_RECEIVE_FILTERS; + + +typedef struct s_pxe_cpb_station_address { + // + // If supplied and supported, the current station MAC address + // will be changed. + // + PXE_MAC_ADDR StationAddr; +} PXE_CPB_STATION_ADDRESS; + + +typedef struct s_pxe_dpb_station_address { + // + // Current station MAC address. + // + PXE_MAC_ADDR StationAddr; + + // + // Station broadcast MAC address. + // + PXE_MAC_ADDR BroadcastAddr; + + // + // Permanent station MAC address. + // + PXE_MAC_ADDR PermanentAddr; +} PXE_DB_STATION_ADDRESS; + + +typedef struct s_pxe_db_statistics { + // + // Bit field identifying what statistic data is collected by the + // UNDI/NIC. + // If bit 0x00 is set, Data[0x00] is collected. + // If bit 0x01 is set, Data[0x01] is collected. + // If bit 0x20 is set, Data[0x20] is collected. + // If bit 0x21 is set, Data[0x21] is collected. + // Etc. + // + PXE_UINT64 Supported; + + // + // Statistic data. + // + PXE_UINT64 Data[64]; +} PXE_DB_STATISTICS; + +// +// Total number of frames received. Includes frames with errors and +// dropped frames. +// +#define PXE_STATISTICS_RX_TOTAL_FRAMES 0x00 + +// +// Number of valid frames received and copied into receive buffers. +// +#define PXE_STATISTICS_RX_GOOD_FRAMES 0x01 + +// +// Number of frames below the minimum length for the media. +// This would be <64 for ethernet. +// +#define PXE_STATISTICS_RX_UNDERSIZE_FRAMES 0x02 + +// +// Number of frames longer than the maxminum length for the +// media. This would be >1500 for ethernet. +// +#define PXE_STATISTICS_RX_OVERSIZE_FRAMES 0x03 + +// +// Valid frames that were dropped because receive buffers were full. +// +#define PXE_STATISTICS_RX_DROPPED_FRAMES 0x04 + +// +// Number of valid unicast frames received and not dropped. +// +#define PXE_STATISTICS_RX_UNICAST_FRAMES 0x05 + +// +// Number of valid broadcast frames received and not dropped. +// +#define PXE_STATISTICS_RX_BROADCAST_FRAMES 0x06 + +// +// Number of valid mutlicast frames received and not dropped. +// +#define PXE_STATISTICS_RX_MULTICAST_FRAMES 0x07 + +// +// Number of frames w/ CRC or alignment errors. +// +#define PXE_STATISTICS_RX_CRC_ERROR_FRAMES 0x08 + +// +// Total number of bytes received. Includes frames with errors +// and dropped frames. +// +#define PXE_STATISTICS_RX_TOTAL_BYTES 0x09 + +// +// Transmit statistics. +// +#define PXE_STATISTICS_TX_TOTAL_FRAMES 0x0A +#define PXE_STATISTICS_TX_GOOD_FRAMES 0x0B +#define PXE_STATISTICS_TX_UNDERSIZE_FRAMES 0x0C +#define PXE_STATISTICS_TX_OVERSIZE_FRAMES 0x0D +#define PXE_STATISTICS_TX_DROPPED_FRAMES 0x0E +#define PXE_STATISTICS_TX_UNICAST_FRAMES 0x0F +#define PXE_STATISTICS_TX_BROADCAST_FRAMES 0x10 +#define PXE_STATISTICS_TX_MULTICAST_FRAMES 0x11 +#define PXE_STATISTICS_TX_CRC_ERROR_FRAMES 0x12 +#define PXE_STATISTICS_TX_TOTAL_BYTES 0x13 + +// +// Number of collisions detection on this subnet. +// +#define PXE_STATISTICS_COLLISIONS 0x14 + +// +// Number of frames destined for unsupported protocol. +// +#define PXE_STATISTICS_UNSUPPORTED_PROTOCOL 0x15 + + +typedef struct s_pxe_cpb_mcast_ip_to_mac { + // + // Multicast IP address to be converted to multicast MAC address. + // + PXE_IP_ADDR IP; +} PXE_CPB_MCAST_IP_TO_MAC; + + +typedef struct s_pxe_db_mcast_ip_to_mac { + // + // Multicast MAC address. + // + PXE_MAC_ADDR MAC; +} PXE_DB_MCAST_IP_TO_MAC; + + +typedef struct s_pxe_cpb_nvdata_sparse { + // + // NvData item list. Only items in this list will be updated. + // + struct { + // Non-volatile storage address to be changed. + PXE_UINT32 Addr; + + // Data item to write into above storage address. + + union { + PXE_UINT8 Byte; + PXE_UINT16 Word; + PXE_UINT32 Dword; + } Data; + } Item[MAX_EEPROM_LEN]; +} PXE_CPB_NVDATA_SPARSE; + + +// +// When using bulk update, the size of the CPB structure must be +// the same size as the non-volatile NIC storage. +// +typedef union u_pxe_cpb_nvdata_bulk { + // + // Array of byte-wide data items. + // + PXE_UINT8 Byte[MAX_EEPROM_LEN << 2]; + + // + // Array of word-wide data items. + // + PXE_UINT16 Word[MAX_EEPROM_LEN << 1]; + + // + // Array of dword-wide data items. + // + PXE_UINT32 Dword[MAX_EEPROM_LEN]; +} PXE_CPB_NVDATA_BULK; + +typedef struct s_pxe_db_nvdata { + + // Arrays of data items from non-volatile storage. + + union { + // + // Array of byte-wide data items. + // + PXE_UINT8 Byte[MAX_EEPROM_LEN << 2]; + + // + // Array of word-wide data items. + // + PXE_UINT16 Word[MAX_EEPROM_LEN << 1]; + + // Array of dword-wide data items. + + PXE_UINT32 Dword[MAX_EEPROM_LEN]; + } Data; +} PXE_DB_NVDATA; + + +typedef struct s_pxe_db_get_status { + // + // Length of next receive frame (header + data). If this is zero, + // there is no next receive frame available. + // + PXE_UINT32 RxFrameLen; + + // + // Reserved, set to zero. + // + PXE_UINT32 reserved; + + // + // Addresses of transmitted buffers that need to be recycled. + // + PXE_UINT64 TxBuffer[MAX_XMIT_BUFFERS]; +} PXE_DB_GET_STATUS; + + + +typedef struct s_pxe_cpb_fill_header { + // + // Source and destination MAC addresses. These will be copied into + // the media header without doing byte swapping. + // + PXE_MAC_ADDR SrcAddr; + PXE_MAC_ADDR DestAddr; + + // + // Address of first byte of media header. The first byte of packet data + // follows the last byte of the media header. + // + PXE_UINT64 MediaHeader; + + // + // Length of packet data in bytes (not including the media header). + // + PXE_UINT32 PacketLen; + + // + // Protocol type. This will be copied into the media header without + // doing byte swapping. Protocol type numbers can be obtained from + // the Assigned Numbers RFC 1700. + // + PXE_UINT16 Protocol; + + // + // Length of the media header in bytes. + // + PXE_UINT16 MediaHeaderLen; +} PXE_CPB_FILL_HEADER; + + +#define PXE_PROTOCOL_ETHERNET_IP 0x0800 +#define PXE_PROTOCOL_ETHERNET_ARP 0x0806 +#define MAX_XMIT_FRAGMENTS 16 + +typedef struct s_pxe_cpb_fill_header_fragmented { + // + // Source and destination MAC addresses. These will be copied into + // the media header without doing byte swapping. + // + PXE_MAC_ADDR SrcAddr; + PXE_MAC_ADDR DestAddr; + + // + // Length of packet data in bytes (not including the media header). + // + PXE_UINT32 PacketLen; + + // + // Protocol type. This will be copied into the media header without + // doing byte swapping. Protocol type numbers can be obtained from + // the Assigned Numbers RFC 1700. + // + PXE_MEDIA_PROTOCOL Protocol; + + // + // Length of the media header in bytes. + // + PXE_UINT16 MediaHeaderLen; + + // + // Number of packet fragment descriptors. + // + PXE_UINT16 FragCnt; + + // + // Reserved, must be set to zero. + // + PXE_UINT16 reserved; + + // + // Array of packet fragment descriptors. The first byte of the media + // header is the first byte of the first fragment. + // + struct { + // + // Address of this packet fragment. + // + PXE_UINT64 FragAddr; + + // + // Length of this packet fragment. + // + PXE_UINT32 FragLen; + + // + // Reserved, must be set to zero. + // + PXE_UINT32 reserved; + } FragDesc[MAX_XMIT_FRAGMENTS]; +} PXE_CPB_FILL_HEADER_FRAGMENTED; + + + +typedef struct s_pxe_cpb_transmit { + // + // Address of first byte of frame buffer. This is also the first byte + // of the media header. + // + PXE_UINT64 FrameAddr; + + // + // Length of the data portion of the frame buffer in bytes. Do not + // include the length of the media header. + // + PXE_UINT32 DataLen; + + // + // Length of the media header in bytes. + // + PXE_UINT16 MediaheaderLen; + + // + // Reserved, must be zero. + // + PXE_UINT16 reserved; +} PXE_CPB_TRANSMIT; + + + +typedef struct s_pxe_cpb_transmit_fragments { + // + // Length of packet data in bytes (not including the media header). + // + PXE_UINT32 FrameLen; + + // + // Length of the media header in bytes. + // + PXE_UINT16 MediaheaderLen; + + // + // Number of packet fragment descriptors. + // + PXE_UINT16 FragCnt; + + // + // Array of frame fragment descriptors. The first byte of the first + // fragment is also the first byte of the media header. + // + struct { + // + // Address of this frame fragment. + // + PXE_UINT64 FragAddr; + + // + // Length of this frame fragment. + // + PXE_UINT32 FragLen; + + // + // Reserved, must be set to zero. + // + PXE_UINT32 reserved; + } FragDesc[MAX_XMIT_FRAGMENTS]; +} PXE_CPB_TRANSMIT_FRAGMENTS; + + +typedef struct s_pxe_cpb_receive { + // + // Address of first byte of receive buffer. This is also the first byte + // of the frame header. + // + PXE_UINT64 BufferAddr; + + // + // Length of receive buffer. This must be large enough to hold the + // received frame (media header + data). If the length of smaller than + // the received frame, data will be lost. + // + PXE_UINT32 BufferLen; + + // + // Reserved, must be set to zero. + // + PXE_UINT32 reserved; +} PXE_CPB_RECEIVE; + + +typedef struct s_pxe_db_receive { + // + // Source and destination MAC addresses from media header. + // + PXE_MAC_ADDR SrcAddr; + PXE_MAC_ADDR DestAddr; + + // + // Length of received frame. May be larger than receive buffer size. + // The receive buffer will not be overwritten. This is how to tell + // if data was lost because the receive buffer was too small. + // + PXE_UINT32 FrameLen; + + // + // Protocol type from media header. + // + PXE_MEDIA_PROTOCOL Protocol; + + // + // Length of media header in received frame. + // + PXE_UINT16 MediaHeaderLen; + + // + // Type of receive frame. + // + PXE_FRAME_TYPE Type; + + // + // Reserved, must be zero. + // + PXE_UINT8 reserved[7]; + +} PXE_DB_RECEIVE; + +#pragma pack() + +/* EOF - efi_pxe.h */ +#endif /* _EFI_PXE_H */ + diff --git a/gnu-efi/inc/efiapi.h b/gnu-efi/inc/efiapi.h new file mode 100644 index 0000000..bdf5de2 --- /dev/null +++ b/gnu-efi/inc/efiapi.h @@ -0,0 +1,967 @@ +#ifndef _EFI_API_H +#define _EFI_API_H + +/*++ + +Copyright (c) 1998 Intel Corporation + +Module Name: + + efiapi.h + +Abstract: + + Global EFI runtime & boot service interfaces + + + + +Revision History + +--*/ + +// +// EFI Specification Revision +// + +#define EFI_SPECIFICATION_MAJOR_REVISION 1 +#define EFI_SPECIFICATION_MINOR_REVISION 02 + +// +// Declare forward referenced data structures +// + +INTERFACE_DECL(_EFI_SYSTEM_TABLE); + +// +// EFI Memory +// + +typedef +EFI_STATUS +(EFIAPI *EFI_ALLOCATE_PAGES) ( + IN EFI_ALLOCATE_TYPE Type, + IN EFI_MEMORY_TYPE MemoryType, + IN UINTN NoPages, + OUT EFI_PHYSICAL_ADDRESS *Memory + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_FREE_PAGES) ( + IN EFI_PHYSICAL_ADDRESS Memory, + IN UINTN NoPages + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_GET_MEMORY_MAP) ( + IN OUT UINTN *MemoryMapSize, + IN OUT EFI_MEMORY_DESCRIPTOR *MemoryMap, + OUT UINTN *MapKey, + OUT UINTN *DescriptorSize, + OUT UINT32 *DescriptorVersion + ); + +#define NextMemoryDescriptor(Ptr,Size) ((EFI_MEMORY_DESCRIPTOR *) (((UINT8 *) Ptr) + Size)) + + +typedef +EFI_STATUS +(EFIAPI *EFI_ALLOCATE_POOL) ( + IN EFI_MEMORY_TYPE PoolType, + IN UINTN Size, + OUT VOID **Buffer + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_FREE_POOL) ( + IN VOID *Buffer + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_SET_VIRTUAL_ADDRESS_MAP) ( + IN UINTN MemoryMapSize, + IN UINTN DescriptorSize, + IN UINT32 DescriptorVersion, + IN EFI_MEMORY_DESCRIPTOR *VirtualMap + ); + + +#define EFI_OPTIONAL_PTR 0x00000001 +#define EFI_INTERNAL_FNC 0x00000002 // Pointer to internal runtime fnc +#define EFI_INTERNAL_PTR 0x00000004 // Pointer to internal runtime data + + +typedef +EFI_STATUS +(EFIAPI *EFI_CONVERT_POINTER) ( + IN UINTN DebugDisposition, + IN OUT VOID **Address + ); + + +// +// EFI Events +// + +#define EVT_TIMER 0x80000000 +#define EVT_RUNTIME 0x40000000 +#define EVT_RUNTIME_CONTEXT 0x20000000 + +#define EVT_NOTIFY_WAIT 0x00000100 +#define EVT_NOTIFY_SIGNAL 0x00000200 + +#define EVT_SIGNAL_EXIT_BOOT_SERVICES 0x00000201 +#define EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE 0x60000202 + +#define EVT_EFI_SIGNAL_MASK 0x000000FF +#define EVT_EFI_SIGNAL_MAX 4 + +#define EFI_EVENT_TIMER EVT_TIMER +#define EFI_EVENT_RUNTIME EVT_RUNTIME +#define EFI_EVENT_RUNTIME_CONTEXT EVT_RUNTIME_CONTEXT +#define EFI_EVENT_NOTIFY_WAIT EVT_NOTIFY_WAIT +#define EFI_EVENT_NOTIFY_SIGNAL EVT_NOTIFY_SIGNAL +#define EFI_EVENT_SIGNAL_EXIT_BOOT_SERVICES EVT_SIGNAL_EXIT_BOOT_SERVICES +#define EFI_EVENT_SIGNAL_VIRTUAL_ADDRESS_CHANGE EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE +#define EFI_EVENT_EFI_SIGNAL_MASK EVT_EFI_SIGNAL_MASK +#define EFI_EVENT_EFI_SIGNAL_MAX EVT_EFI_SIGNAL_MAX + + +typedef +VOID +(EFIAPI *EFI_EVENT_NOTIFY) ( + IN EFI_EVENT Event, + IN VOID *Context + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_CREATE_EVENT) ( + IN UINT32 Type, + IN EFI_TPL NotifyTpl, + IN EFI_EVENT_NOTIFY NotifyFunction, + IN VOID *NotifyContext, + OUT EFI_EVENT *Event + ); + +typedef enum { + TimerCancel, + TimerPeriodic, + TimerRelative, + TimerTypeMax +} EFI_TIMER_DELAY; + +typedef +EFI_STATUS +(EFIAPI *EFI_SET_TIMER) ( + IN EFI_EVENT Event, + IN EFI_TIMER_DELAY Type, + IN UINT64 TriggerTime + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_SIGNAL_EVENT) ( + IN EFI_EVENT Event + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_WAIT_FOR_EVENT) ( + IN UINTN NumberOfEvents, + IN EFI_EVENT *Event, + OUT UINTN *Index + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_CLOSE_EVENT) ( + IN EFI_EVENT Event + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_CHECK_EVENT) ( + IN EFI_EVENT Event + ); + +// +// Task priority level +// + +#define TPL_APPLICATION 4 +#define TPL_CALLBACK 8 +#define TPL_NOTIFY 16 +#define TPL_HIGH_LEVEL 31 +#define EFI_TPL_APPLICATION TPL_APPLICATION +#define EFI_TPL_CALLBACK TPL_CALLBACK +#define EFI_TPL_NOTIFY TPL_NOTIFY +#define EFI_TPL_HIGH_LEVEL TPL_HIGH_LEVEL +typedef +EFI_TPL +(EFIAPI *EFI_RAISE_TPL) ( + IN EFI_TPL NewTpl + ); + +typedef +VOID +(EFIAPI *EFI_RESTORE_TPL) ( + IN EFI_TPL OldTpl + ); + + +// +// EFI platform varibles +// + +#define EFI_GLOBAL_VARIABLE \ + { 0x8BE4DF61, 0x93CA, 0x11d2, {0xAA, 0x0D, 0x00, 0xE0, 0x98, 0x03, 0x2B, 0x8C} } + +// Variable attributes +#define EFI_VARIABLE_NON_VOLATILE 0x00000001 +#define EFI_VARIABLE_BOOTSERVICE_ACCESS 0x00000002 +#define EFI_VARIABLE_RUNTIME_ACCESS 0x00000004 +#define EFI_VARIABLE_HARDWARE_ERROR_RECORD 0x00000008 +#define EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS 0x00000010 +#define EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS 0x00000020 +#define EFI_VARIABLE_APPEND_WRITE 0x00000040 + +// Variable size limitation +#define EFI_MAXIMUM_VARIABLE_SIZE 1024 + +typedef +EFI_STATUS +(EFIAPI *EFI_GET_VARIABLE) ( + IN CHAR16 *VariableName, + IN EFI_GUID *VendorGuid, + OUT UINT32 *Attributes OPTIONAL, + IN OUT UINTN *DataSize, + OUT VOID *Data + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_GET_NEXT_VARIABLE_NAME) ( + IN OUT UINTN *VariableNameSize, + IN OUT CHAR16 *VariableName, + IN OUT EFI_GUID *VendorGuid + ); + + +typedef +EFI_STATUS +(EFIAPI *EFI_SET_VARIABLE) ( + IN CHAR16 *VariableName, + IN EFI_GUID *VendorGuid, + IN UINT32 Attributes, + IN UINTN DataSize, + IN VOID *Data + ); + + +// +// EFI Time +// + +typedef struct { + UINT32 Resolution; // 1e-6 parts per million + UINT32 Accuracy; // hertz + BOOLEAN SetsToZero; // Set clears sub-second time +} EFI_TIME_CAPABILITIES; + + +typedef +EFI_STATUS +(EFIAPI *EFI_GET_TIME) ( + OUT EFI_TIME *Time, + OUT EFI_TIME_CAPABILITIES *Capabilities OPTIONAL + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_SET_TIME) ( + IN EFI_TIME *Time + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_GET_WAKEUP_TIME) ( + OUT BOOLEAN *Enabled, + OUT BOOLEAN *Pending, + OUT EFI_TIME *Time + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_SET_WAKEUP_TIME) ( + IN BOOLEAN Enable, + IN EFI_TIME *Time OPTIONAL + ); + + +// +// Image functions +// + + +// PE32+ Subsystem type for EFI images + +#if !defined(IMAGE_SUBSYSTEM_EFI_APPLICATION) +#define IMAGE_SUBSYSTEM_EFI_APPLICATION 10 +#define IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER 11 +#define IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER 12 +#endif + +// PE32+ Machine type for EFI images + +#if !defined(EFI_IMAGE_MACHINE_IA32) +#define EFI_IMAGE_MACHINE_IA32 0x014c +#endif + +#if !defined(EFI_IMAGE_MACHINE_IA64) +#define EFI_IMAGE_MACHINE_IA64 0x0200 +#endif + +#if !defined(EFI_IMAGE_MACHINE_EBC) +#define EFI_IMAGE_MACHINE_EBC 0x0EBC +#endif + +#if !defined(EFI_IMAGE_MACHINE_X64) +#define EFI_IMAGE_MACHINE_X64 0x8664 +#endif + +#if !defined(EFI_IMAGE_MACHINE_ARMTHUMB_MIXED) +#define EFI_IMAGE_MACHINE_ARMTHUMB_MIXED 0x01C2 +#endif + +#if !defined(EFI_IMAGE_MACHINE_AARCH64) +#define EFI_IMAGE_MACHINE_AARCH64 0xAA64 +#endif + +// Image Entry prototype + +typedef +EFI_STATUS +(EFIAPI *EFI_IMAGE_ENTRY_POINT) ( + IN EFI_HANDLE ImageHandle, + IN struct _EFI_SYSTEM_TABLE *SystemTable + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_IMAGE_LOAD) ( + IN BOOLEAN BootPolicy, + IN EFI_HANDLE ParentImageHandle, + IN EFI_DEVICE_PATH *FilePath, + IN VOID *SourceBuffer OPTIONAL, + IN UINTN SourceSize, + OUT EFI_HANDLE *ImageHandle + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_IMAGE_START) ( + IN EFI_HANDLE ImageHandle, + OUT UINTN *ExitDataSize, + OUT CHAR16 **ExitData OPTIONAL + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_EXIT) ( + IN EFI_HANDLE ImageHandle, + IN EFI_STATUS ExitStatus, + IN UINTN ExitDataSize, + IN CHAR16 *ExitData OPTIONAL + ); + + +// Image handle +/*#define LOADED_IMAGE_PROTOCOL \ + { 0x5B1B31A1, 0x9562, 0x11d2, {0x8E, 0x3F, 0x00, 0xA0, 0xC9, 0x69, 0x72, 0x3B} } + +#define EFI_IMAGE_INFORMATION_REVISION 0x1000 +typedef struct { + UINT32 Revision; + EFI_HANDLE ParentHandle; + struct _EFI_SYSTEM_TABLE *SystemTable; + + // Source location of image + EFI_HANDLE DeviceHandle; + EFI_DEVICE_PATH *FilePath; + VOID *Reserved; + + // Images load options + UINT32 LoadOptionsSize; + VOID *LoadOptions; + + // Location of where image was loaded + VOID *ImageBase; + UINT64 ImageSize; + EFI_MEMORY_TYPE ImageCodeType; + EFI_MEMORY_TYPE ImageDataType; + + // If the driver image supports a dynamic unload request + EFI_IMAGE_UNLOAD Unload; + +} EFI_LOADED_IMAGE;*/ + + +typedef +EFI_STATUS +(EFIAPI *EFI_EXIT_BOOT_SERVICES) ( + IN EFI_HANDLE ImageHandle, + IN UINTN MapKey + ); + +// +// Misc +// + + +typedef +EFI_STATUS +(EFIAPI *EFI_STALL) ( + IN UINTN Microseconds + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_SET_WATCHDOG_TIMER) ( + IN UINTN Timeout, + IN UINT64 WatchdogCode, + IN UINTN DataSize, + IN CHAR16 *WatchdogData OPTIONAL + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_CONNECT_CONTROLLER) ( + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE *DriverImageHandle OPTIONAL, + IN EFI_DEVICE_PATH *RemainingDevicePath OPTIONAL, + IN BOOLEAN Recursive + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_DISCONNECT_CONTROLLER) ( + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE DriverImageHandle OPTIONAL, + IN EFI_HANDLE ChildHandle OPTIONAL + ); + +#define EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL 0x00000001 +#define EFI_OPEN_PROTOCOL_GET_PROTOCOL 0x00000002 +#define EFI_OPEN_PROTOCOL_TEST_PROTOCOL 0x00000004 +#define EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER 0x00000008 +#define EFI_OPEN_PROTOCOL_BY_DRIVER 0x00000010 +#define EFI_OPEN_PROTOCOL_EXCLUSIVE 0x00000020 + +typedef +EFI_STATUS +(EFIAPI *EFI_OPEN_PROTOCOL) ( + IN EFI_HANDLE Handle, + IN EFI_GUID *Protocol, + OUT VOID **Interface OPTIONAL, + IN EFI_HANDLE AgentHandle, + IN EFI_HANDLE ControllerHandle, + IN UINT32 Attributes + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_CLOSE_PROTOCOL) ( + IN EFI_HANDLE Handle, + IN EFI_GUID *Protocol, + IN EFI_HANDLE AgentHandle, + IN EFI_HANDLE ControllerHandle + ); + +typedef struct { + EFI_HANDLE AgentHandle; + EFI_HANDLE ControllerHandle; + UINT32 Attributes; + UINT32 OpenCount; +} EFI_OPEN_PROTOCOL_INFORMATION_ENTRY; + +typedef +EFI_STATUS +(EFIAPI *EFI_OPEN_PROTOCOL_INFORMATION) ( + IN EFI_HANDLE Handle, + IN EFI_GUID *Protocol, + OUT EFI_OPEN_PROTOCOL_INFORMATION_ENTRY **EntryBuffer, + OUT UINTN *EntryCount + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_PROTOCOLS_PER_HANDLE) ( + IN EFI_HANDLE Handle, + OUT EFI_GUID ***ProtocolBuffer, + OUT UINTN *ProtocolBufferCount + ); + +typedef enum { + AllHandles, + ByRegisterNotify, + ByProtocol +} EFI_LOCATE_SEARCH_TYPE; + +typedef +EFI_STATUS +(EFIAPI *EFI_LOCATE_HANDLE_BUFFER) ( + IN EFI_LOCATE_SEARCH_TYPE SearchType, + IN EFI_GUID *Protocol OPTIONAL, + IN VOID *SearchKey OPTIONAL, + IN OUT UINTN *NoHandles, + OUT EFI_HANDLE **Buffer + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_LOCATE_PROTOCOL) ( + IN EFI_GUID *Protocol, + IN VOID *Registration OPTIONAL, + OUT VOID **Interface + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_INSTALL_MULTIPLE_PROTOCOL_INTERFACES) ( + IN OUT EFI_HANDLE *Handle, + ... + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_UNINSTALL_MULTIPLE_PROTOCOL_INTERFACES) ( + IN OUT EFI_HANDLE Handle, + ... + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_CALCULATE_CRC32) ( + IN VOID *Data, + IN UINTN DataSize, + OUT UINT32 *Crc32 + ); + +typedef +VOID +(EFIAPI *EFI_COPY_MEM) ( + IN VOID *Destination, + IN VOID *Source, + IN UINTN Length + ); + +typedef +VOID +(EFIAPI *EFI_SET_MEM) ( + IN VOID *Buffer, + IN UINTN Size, + IN UINT8 Value + ); + + +typedef +EFI_STATUS +(EFIAPI *EFI_CREATE_EVENT_EX) ( + IN UINT32 Type, + IN EFI_TPL NotifyTpl, + IN EFI_EVENT_NOTIFY NotifyFunction OPTIONAL, + IN const VOID *NotifyContext OPTIONAL, + IN const EFI_GUID *EventGroup OPTIONAL, + OUT EFI_EVENT *Event + ); + +typedef enum { + EfiResetCold, + EfiResetWarm, + EfiResetShutdown +} EFI_RESET_TYPE; + +typedef +EFI_STATUS +(EFIAPI *EFI_RESET_SYSTEM) ( + IN EFI_RESET_TYPE ResetType, + IN EFI_STATUS ResetStatus, + IN UINTN DataSize, + IN CHAR16 *ResetData OPTIONAL + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_GET_NEXT_MONOTONIC_COUNT) ( + OUT UINT64 *Count + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_GET_NEXT_HIGH_MONO_COUNT) ( + OUT UINT32 *HighCount + ); + +typedef struct { + UINT64 Length; + union { + EFI_PHYSICAL_ADDRESS DataBlock; + EFI_PHYSICAL_ADDRESS ContinuationPointer; + } Union; +} EFI_CAPSULE_BLOCK_DESCRIPTOR; + +typedef struct { + EFI_GUID CapsuleGuid; + UINT32 HeaderSize; + UINT32 Flags; + UINT32 CapsuleImageSize; +} EFI_CAPSULE_HEADER; + +#define CAPSULE_FLAGS_PERSIST_ACROSS_RESET 0x00010000 +#define CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE 0x00020000 +#define CAPSULE_FLAGS_INITIATE_RESET 0x00040000 + +typedef +EFI_STATUS +(EFIAPI *EFI_UPDATE_CAPSULE) ( + IN EFI_CAPSULE_HEADER **CapsuleHeaderArray, + IN UINTN CapsuleCount, + IN EFI_PHYSICAL_ADDRESS ScatterGatherList OPTIONAL + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_QUERY_CAPSULE_CAPABILITIES) ( + IN EFI_CAPSULE_HEADER **CapsuleHeaderArray, + IN UINTN CapsuleCount, + OUT UINT64 *MaximumCapsuleSize, + OUT EFI_RESET_TYPE *ResetType + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_QUERY_VARIABLE_INFO) ( + IN UINT32 Attributes, + OUT UINT64 *MaximumVariableStorageSize, + OUT UINT64 *RemainingVariableStorageSize, + OUT UINT64 *MaximumVariableSize + ); + +// +// Protocol handler functions +// + +typedef enum { + EFI_NATIVE_INTERFACE, + EFI_PCODE_INTERFACE +} EFI_INTERFACE_TYPE; + +typedef +EFI_STATUS +(EFIAPI *EFI_INSTALL_PROTOCOL_INTERFACE) ( + IN OUT EFI_HANDLE *Handle, + IN EFI_GUID *Protocol, + IN EFI_INTERFACE_TYPE InterfaceType, + IN VOID *Interface + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_REINSTALL_PROTOCOL_INTERFACE) ( + IN EFI_HANDLE Handle, + IN EFI_GUID *Protocol, + IN VOID *OldInterface, + IN VOID *NewInterface + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_UNINSTALL_PROTOCOL_INTERFACE) ( + IN EFI_HANDLE Handle, + IN EFI_GUID *Protocol, + IN VOID *Interface + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_HANDLE_PROTOCOL) ( + IN EFI_HANDLE Handle, + IN EFI_GUID *Protocol, + OUT VOID **Interface + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_REGISTER_PROTOCOL_NOTIFY) ( + IN EFI_GUID *Protocol, + IN EFI_EVENT Event, + OUT VOID **Registration + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_LOCATE_HANDLE) ( + IN EFI_LOCATE_SEARCH_TYPE SearchType, + IN EFI_GUID *Protocol OPTIONAL, + IN VOID *SearchKey OPTIONAL, + IN OUT UINTN *BufferSize, + OUT EFI_HANDLE *Buffer + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_LOCATE_DEVICE_PATH) ( + IN EFI_GUID *Protocol, + IN OUT EFI_DEVICE_PATH **DevicePath, + OUT EFI_HANDLE *Device + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_INSTALL_CONFIGURATION_TABLE) ( + IN EFI_GUID *Guid, + IN VOID *Table + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_RESERVED_SERVICE) ( + ); + +// +// Standard EFI table header +// + +typedef struct _EFI_TABLE_HEADER { + UINT64 Signature; + UINT32 Revision; + UINT32 HeaderSize; + UINT32 CRC32; + UINT32 Reserved; +} EFI_TABLE_HEADER; + + +// +// EFI Runtime Serivces Table +// + +#define EFI_RUNTIME_SERVICES_SIGNATURE 0x56524553544e5552 +#define EFI_RUNTIME_SERVICES_REVISION (EFI_SPECIFICATION_MAJOR_REVISION<<16) | (EFI_SPECIFICATION_MINOR_REVISION) + +typedef struct { + EFI_TABLE_HEADER Hdr; + + // + // Time services + // + + EFI_GET_TIME GetTime; + EFI_SET_TIME SetTime; + EFI_GET_WAKEUP_TIME GetWakeupTime; + EFI_SET_WAKEUP_TIME SetWakeupTime; + + // + // Virtual memory services + // + + EFI_SET_VIRTUAL_ADDRESS_MAP SetVirtualAddressMap; + EFI_CONVERT_POINTER ConvertPointer; + + // + // Variable serviers + // + + EFI_GET_VARIABLE GetVariable; + EFI_GET_NEXT_VARIABLE_NAME GetNextVariableName; + EFI_SET_VARIABLE SetVariable; + + // + // Misc + // + + EFI_GET_NEXT_HIGH_MONO_COUNT GetNextHighMonotonicCount; + EFI_RESET_SYSTEM ResetSystem; + + EFI_UPDATE_CAPSULE UpdateCapsule; + EFI_QUERY_CAPSULE_CAPABILITIES QueryCapsuleCapabilities; + EFI_QUERY_VARIABLE_INFO QueryVariableInfo; +} EFI_RUNTIME_SERVICES; + + +// +// EFI Boot Services Table +// + +#define EFI_BOOT_SERVICES_SIGNATURE 0x56524553544f4f42 +#define EFI_BOOT_SERVICES_REVISION (EFI_SPECIFICATION_MAJOR_REVISION<<16) | (EFI_SPECIFICATION_MINOR_REVISION) + +typedef struct _EFI_BOOT_SERVICES { + + EFI_TABLE_HEADER Hdr; + + // + // Task priority functions + // + + EFI_RAISE_TPL RaiseTPL; + EFI_RESTORE_TPL RestoreTPL; + + // + // Memory functions + // + + EFI_ALLOCATE_PAGES AllocatePages; + EFI_FREE_PAGES FreePages; + EFI_GET_MEMORY_MAP GetMemoryMap; + EFI_ALLOCATE_POOL AllocatePool; + EFI_FREE_POOL FreePool; + + // + // Event & timer functions + // + + EFI_CREATE_EVENT CreateEvent; + EFI_SET_TIMER SetTimer; + EFI_WAIT_FOR_EVENT WaitForEvent; + EFI_SIGNAL_EVENT SignalEvent; + EFI_CLOSE_EVENT CloseEvent; + EFI_CHECK_EVENT CheckEvent; + + // + // Protocol handler functions + // + + EFI_INSTALL_PROTOCOL_INTERFACE InstallProtocolInterface; + EFI_REINSTALL_PROTOCOL_INTERFACE ReinstallProtocolInterface; + EFI_UNINSTALL_PROTOCOL_INTERFACE UninstallProtocolInterface; + EFI_HANDLE_PROTOCOL HandleProtocol; + EFI_HANDLE_PROTOCOL PCHandleProtocol; + EFI_REGISTER_PROTOCOL_NOTIFY RegisterProtocolNotify; + EFI_LOCATE_HANDLE LocateHandle; + EFI_LOCATE_DEVICE_PATH LocateDevicePath; + EFI_INSTALL_CONFIGURATION_TABLE InstallConfigurationTable; + + // + // Image functions + // + + EFI_IMAGE_LOAD LoadImage; + EFI_IMAGE_START StartImage; + EFI_EXIT Exit; + EFI_IMAGE_UNLOAD UnloadImage; + EFI_EXIT_BOOT_SERVICES ExitBootServices; + + // + // Misc functions + // + + EFI_GET_NEXT_MONOTONIC_COUNT GetNextMonotonicCount; + EFI_STALL Stall; + EFI_SET_WATCHDOG_TIMER SetWatchdogTimer; + + // + // DriverSupport Services + // + + EFI_CONNECT_CONTROLLER ConnectController; + EFI_DISCONNECT_CONTROLLER DisconnectController; + + // + // Open and Close Protocol Services + // + EFI_OPEN_PROTOCOL OpenProtocol; + EFI_CLOSE_PROTOCOL CloseProtocol; + EFI_OPEN_PROTOCOL_INFORMATION OpenProtocolInformation; + + // + // Library Services + // + EFI_PROTOCOLS_PER_HANDLE ProtocolsPerHandle; + EFI_LOCATE_HANDLE_BUFFER LocateHandleBuffer; + EFI_LOCATE_PROTOCOL LocateProtocol; + EFI_INSTALL_MULTIPLE_PROTOCOL_INTERFACES InstallMultipleProtocolInterfaces; + EFI_UNINSTALL_MULTIPLE_PROTOCOL_INTERFACES UninstallMultipleProtocolInterfaces; + + // + // 32-bit CRC Services + // + EFI_CALCULATE_CRC32 CalculateCrc32; + + // + // Misc Services + // + EFI_COPY_MEM CopyMem; + EFI_SET_MEM SetMem; + EFI_CREATE_EVENT_EX CreateEventEx; +} EFI_BOOT_SERVICES; + + +// +// EFI Configuration Table and GUID definitions +// + +#define MPS_TABLE_GUID \ + { 0xeb9d2d2f, 0x2d88, 0x11d3, {0x9a, 0x16, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d} } + +#define ACPI_TABLE_GUID \ + { 0xeb9d2d30, 0x2d88, 0x11d3, {0x9a, 0x16, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d} } + +#define ACPI_20_TABLE_GUID \ + { 0x8868e871, 0xe4f1, 0x11d3, {0xbc, 0x22, 0x0, 0x80, 0xc7, 0x3c, 0x88, 0x81} } + +#define SMBIOS_TABLE_GUID \ + { 0xeb9d2d31, 0x2d88, 0x11d3, {0x9a, 0x16, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d} } + +#define SMBIOS3_TABLE_GUID \ + { 0xf2fd1544, 0x9794, 0x4a2c, {0x99, 0x2e, 0xe5, 0xbb, 0xcf, 0x20, 0xe3, 0x94} } + +#define SAL_SYSTEM_TABLE_GUID \ + { 0xeb9d2d32, 0x2d88, 0x11d3, {0x9a, 0x16, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d} } + + +typedef struct _EFI_CONFIGURATION_TABLE { + EFI_GUID VendorGuid; + VOID *VendorTable; +} EFI_CONFIGURATION_TABLE; + + +// +// EFI System Table +// + + + + +#define EFI_SYSTEM_TABLE_SIGNATURE 0x5453595320494249 +#define EFI_SYSTEM_TABLE_REVISION (EFI_SPECIFICATION_MAJOR_REVISION<<16) | (EFI_SPECIFICATION_MINOR_REVISION) + +typedef struct _EFI_SYSTEM_TABLE { + EFI_TABLE_HEADER Hdr; + + CHAR16 *FirmwareVendor; + UINT32 FirmwareRevision; + + EFI_HANDLE ConsoleInHandle; + SIMPLE_INPUT_INTERFACE *ConIn; + + EFI_HANDLE ConsoleOutHandle; + SIMPLE_TEXT_OUTPUT_INTERFACE *ConOut; + + EFI_HANDLE StandardErrorHandle; + SIMPLE_TEXT_OUTPUT_INTERFACE *StdErr; + + EFI_RUNTIME_SERVICES *RuntimeServices; + EFI_BOOT_SERVICES *BootServices; + + UINTN NumberOfTableEntries; + EFI_CONFIGURATION_TABLE *ConfigurationTable; + +} EFI_SYSTEM_TABLE; + +#endif + diff --git a/gnu-efi/inc/eficompiler.h b/gnu-efi/inc/eficompiler.h new file mode 100644 index 0000000..26636c7 --- /dev/null +++ b/gnu-efi/inc/eficompiler.h @@ -0,0 +1,30 @@ +/*++ + +Copyright (c) 2016 Pete Batard + +Module Name: + + eficompiler.h + +Abstract: + + Compiler specific adjustments + +--*/ + +#ifdef _MSC_EXTENSIONS +#define EFI_UNUSED +#else +#define EFI_UNUSED __attribute__((__unused__)) +#endif + +#ifdef _MSC_EXTENSIONS +#define ALIGN(x) __declspec(align(x)) +#else +#define ALIGN(x) __attribute__((__aligned__(x))) +#endif + +/* Also add a catch-all on __attribute__() for MS compilers */ +#ifdef _MSC_EXTENSIONS +#define __attribute__(x) +#endif diff --git a/gnu-efi/inc/eficon.h b/gnu-efi/inc/eficon.h new file mode 100644 index 0000000..5d17e04 --- /dev/null +++ b/gnu-efi/inc/eficon.h @@ -0,0 +1,306 @@ +#ifndef _EFI_CON_H +#define _EFI_CON_H + +/*++ + +Copyright (c) 1998 Intel Corporation + +Module Name: + + eficon.h + +Abstract: + + EFI console protocols + + + +Revision History + +--*/ + +// +// Text output protocol +// + +#define EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL_GUID \ + { 0x387477c2, 0x69c7, 0x11d2, {0x8e, 0x39, 0x0, 0xa0, 0xc9, 0x69, 0x72, 0x3b} } +#define SIMPLE_TEXT_OUTPUT_PROTOCOL EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL_GUID + +INTERFACE_DECL(_SIMPLE_TEXT_OUTPUT_INTERFACE); + +typedef +EFI_STATUS +(EFIAPI *EFI_TEXT_RESET) ( + IN struct _SIMPLE_TEXT_OUTPUT_INTERFACE *This, + IN BOOLEAN ExtendedVerification + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_TEXT_OUTPUT_STRING) ( + IN struct _SIMPLE_TEXT_OUTPUT_INTERFACE *This, + IN CHAR16 *String + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_TEXT_TEST_STRING) ( + IN struct _SIMPLE_TEXT_OUTPUT_INTERFACE *This, + IN CHAR16 *String + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_TEXT_QUERY_MODE) ( + IN struct _SIMPLE_TEXT_OUTPUT_INTERFACE *This, + IN UINTN ModeNumber, + OUT UINTN *Columns, + OUT UINTN *Rows + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_TEXT_SET_MODE) ( + IN struct _SIMPLE_TEXT_OUTPUT_INTERFACE *This, + IN UINTN ModeNumber + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_TEXT_SET_ATTRIBUTE) ( + IN struct _SIMPLE_TEXT_OUTPUT_INTERFACE *This, + IN UINTN Attribute + ); + +#define EFI_BLACK 0x00 +#define EFI_BLUE 0x01 +#define EFI_GREEN 0x02 +#define EFI_CYAN (EFI_BLUE | EFI_GREEN) +#define EFI_RED 0x04 +#define EFI_MAGENTA (EFI_BLUE | EFI_RED) +#define EFI_BROWN (EFI_GREEN | EFI_RED) +#define EFI_LIGHTGRAY (EFI_BLUE | EFI_GREEN | EFI_RED) +#define EFI_BRIGHT 0x08 +#define EFI_DARKGRAY (EFI_BRIGHT) +#define EFI_LIGHTBLUE (EFI_BLUE | EFI_BRIGHT) +#define EFI_LIGHTGREEN (EFI_GREEN | EFI_BRIGHT) +#define EFI_LIGHTCYAN (EFI_CYAN | EFI_BRIGHT) +#define EFI_LIGHTRED (EFI_RED | EFI_BRIGHT) +#define EFI_LIGHTMAGENTA (EFI_MAGENTA | EFI_BRIGHT) +#define EFI_YELLOW (EFI_BROWN | EFI_BRIGHT) +#define EFI_WHITE (EFI_BLUE | EFI_GREEN | EFI_RED | EFI_BRIGHT) + +#define EFI_TEXT_ATTR(f,b) ((f) | ((b) << 4)) + +#define EFI_BACKGROUND_BLACK 0x00 +#define EFI_BACKGROUND_BLUE 0x10 +#define EFI_BACKGROUND_GREEN 0x20 +#define EFI_BACKGROUND_CYAN (EFI_BACKGROUND_BLUE | EFI_BACKGROUND_GREEN) +#define EFI_BACKGROUND_RED 0x40 +#define EFI_BACKGROUND_MAGENTA (EFI_BACKGROUND_BLUE | EFI_BACKGROUND_RED) +#define EFI_BACKGROUND_BROWN (EFI_BACKGROUND_GREEN | EFI_BACKGROUND_RED) +#define EFI_BACKGROUND_LIGHTGRAY (EFI_BACKGROUND_BLUE | EFI_BACKGROUND_GREEN | EFI_BACKGROUND_RED) + + +typedef +EFI_STATUS +(EFIAPI *EFI_TEXT_CLEAR_SCREEN) ( + IN struct _SIMPLE_TEXT_OUTPUT_INTERFACE *This + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_TEXT_SET_CURSOR_POSITION) ( + IN struct _SIMPLE_TEXT_OUTPUT_INTERFACE *This, + IN UINTN Column, + IN UINTN Row + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_TEXT_ENABLE_CURSOR) ( + IN struct _SIMPLE_TEXT_OUTPUT_INTERFACE *This, + IN BOOLEAN Enable + ); + +typedef struct { + INT32 MaxMode; + // current settings + INT32 Mode; + INT32 Attribute; + INT32 CursorColumn; + INT32 CursorRow; + BOOLEAN CursorVisible; +} SIMPLE_TEXT_OUTPUT_MODE; + +typedef struct _SIMPLE_TEXT_OUTPUT_INTERFACE { + EFI_TEXT_RESET Reset; + + EFI_TEXT_OUTPUT_STRING OutputString; + EFI_TEXT_TEST_STRING TestString; + + EFI_TEXT_QUERY_MODE QueryMode; + EFI_TEXT_SET_MODE SetMode; + EFI_TEXT_SET_ATTRIBUTE SetAttribute; + + EFI_TEXT_CLEAR_SCREEN ClearScreen; + EFI_TEXT_SET_CURSOR_POSITION SetCursorPosition; + EFI_TEXT_ENABLE_CURSOR EnableCursor; + + // Current mode + SIMPLE_TEXT_OUTPUT_MODE *Mode; +} SIMPLE_TEXT_OUTPUT_INTERFACE, EFI_SIMPLE_TEXT_OUT_PROTOCOL; + +// +// Define's for required EFI Unicode Box Draw character +// + +#define BOXDRAW_HORIZONTAL 0x2500 +#define BOXDRAW_VERTICAL 0x2502 +#define BOXDRAW_DOWN_RIGHT 0x250c +#define BOXDRAW_DOWN_LEFT 0x2510 +#define BOXDRAW_UP_RIGHT 0x2514 +#define BOXDRAW_UP_LEFT 0x2518 +#define BOXDRAW_VERTICAL_RIGHT 0x251c +#define BOXDRAW_VERTICAL_LEFT 0x2524 +#define BOXDRAW_DOWN_HORIZONTAL 0x252c +#define BOXDRAW_UP_HORIZONTAL 0x2534 +#define BOXDRAW_VERTICAL_HORIZONTAL 0x253c + +#define BOXDRAW_DOUBLE_HORIZONTAL 0x2550 +#define BOXDRAW_DOUBLE_VERTICAL 0x2551 +#define BOXDRAW_DOWN_RIGHT_DOUBLE 0x2552 +#define BOXDRAW_DOWN_DOUBLE_RIGHT 0x2553 +#define BOXDRAW_DOUBLE_DOWN_RIGHT 0x2554 + +#define BOXDRAW_DOWN_LEFT_DOUBLE 0x2555 +#define BOXDRAW_DOWN_DOUBLE_LEFT 0x2556 +#define BOXDRAW_DOUBLE_DOWN_LEFT 0x2557 + +#define BOXDRAW_UP_RIGHT_DOUBLE 0x2558 +#define BOXDRAW_UP_DOUBLE_RIGHT 0x2559 +#define BOXDRAW_DOUBLE_UP_RIGHT 0x255a + +#define BOXDRAW_UP_LEFT_DOUBLE 0x255b +#define BOXDRAW_UP_DOUBLE_LEFT 0x255c +#define BOXDRAW_DOUBLE_UP_LEFT 0x255d + +#define BOXDRAW_VERTICAL_RIGHT_DOUBLE 0x255e +#define BOXDRAW_VERTICAL_DOUBLE_RIGHT 0x255f +#define BOXDRAW_DOUBLE_VERTICAL_RIGHT 0x2560 + +#define BOXDRAW_VERTICAL_LEFT_DOUBLE 0x2561 +#define BOXDRAW_VERTICAL_DOUBLE_LEFT 0x2562 +#define BOXDRAW_DOUBLE_VERTICAL_LEFT 0x2563 + +#define BOXDRAW_DOWN_HORIZONTAL_DOUBLE 0x2564 +#define BOXDRAW_DOWN_DOUBLE_HORIZONTAL 0x2565 +#define BOXDRAW_DOUBLE_DOWN_HORIZONTAL 0x2566 + +#define BOXDRAW_UP_HORIZONTAL_DOUBLE 0x2567 +#define BOXDRAW_UP_DOUBLE_HORIZONTAL 0x2568 +#define BOXDRAW_DOUBLE_UP_HORIZONTAL 0x2569 + +#define BOXDRAW_VERTICAL_HORIZONTAL_DOUBLE 0x256a +#define BOXDRAW_VERTICAL_DOUBLE_HORIZONTAL 0x256b +#define BOXDRAW_DOUBLE_VERTICAL_HORIZONTAL 0x256c + +// +// EFI Required Block Elements Code Chart +// + +#define BLOCKELEMENT_FULL_BLOCK 0x2588 +#define BLOCKELEMENT_LIGHT_SHADE 0x2591 +// +// EFI Required Geometric Shapes Code Chart +// + +#define GEOMETRICSHAPE_UP_TRIANGLE 0x25b2 +#define GEOMETRICSHAPE_RIGHT_TRIANGLE 0x25ba +#define GEOMETRICSHAPE_DOWN_TRIANGLE 0x25bc +#define GEOMETRICSHAPE_LEFT_TRIANGLE 0x25c4 + +// +// EFI Required Arrow shapes +// + +#define ARROW_UP 0x2191 +#define ARROW_DOWN 0x2193 + +// +// Text input protocol +// + +#define EFI_SIMPLE_TEXT_INPUT_PROTOCOL_GUID \ + { 0x387477c1, 0x69c7, 0x11d2, {0x8e, 0x39, 0x0, 0xa0, 0xc9, 0x69, 0x72, 0x3b} } +#define SIMPLE_TEXT_INPUT_PROTOCOL EFI_SIMPLE_TEXT_INPUT_PROTOCOL_GUID + +INTERFACE_DECL(_SIMPLE_INPUT_INTERFACE); + +typedef struct { + UINT16 ScanCode; + CHAR16 UnicodeChar; +} EFI_INPUT_KEY; + +// +// Baseline unicode control chars +// + +#define CHAR_NULL 0x0000 +#define CHAR_BACKSPACE 0x0008 +#define CHAR_TAB 0x0009 +#define CHAR_LINEFEED 0x000A +#define CHAR_CARRIAGE_RETURN 0x000D + +// +// Scan codes for base line keys +// + +#define SCAN_NULL 0x0000 +#define SCAN_UP 0x0001 +#define SCAN_DOWN 0x0002 +#define SCAN_RIGHT 0x0003 +#define SCAN_LEFT 0x0004 +#define SCAN_HOME 0x0005 +#define SCAN_END 0x0006 +#define SCAN_INSERT 0x0007 +#define SCAN_DELETE 0x0008 +#define SCAN_PAGE_UP 0x0009 +#define SCAN_PAGE_DOWN 0x000A +#define SCAN_F1 0x000B +#define SCAN_F2 0x000C +#define SCAN_F3 0x000D +#define SCAN_F4 0x000E +#define SCAN_F5 0x000F +#define SCAN_F6 0x0010 +#define SCAN_F7 0x0011 +#define SCAN_F8 0x0012 +#define SCAN_F9 0x0013 +#define SCAN_F10 0x0014 +#define SCAN_F11 0x0015 +#define SCAN_F12 0x0016 +#define SCAN_ESC 0x0017 + +typedef +EFI_STATUS +(EFIAPI *EFI_INPUT_RESET) ( + IN struct _SIMPLE_INPUT_INTERFACE *This, + IN BOOLEAN ExtendedVerification + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_INPUT_READ_KEY) ( + IN struct _SIMPLE_INPUT_INTERFACE *This, + OUT EFI_INPUT_KEY *Key + ); + +typedef struct _SIMPLE_INPUT_INTERFACE { + EFI_INPUT_RESET Reset; + EFI_INPUT_READ_KEY ReadKeyStroke; + EFI_EVENT WaitForKey; +} SIMPLE_INPUT_INTERFACE, EFI_SIMPLE_TEXT_IN_PROTOCOL; + +#endif + diff --git a/gnu-efi/inc/efidebug.h b/gnu-efi/inc/efidebug.h new file mode 100644 index 0000000..8e54dcd --- /dev/null +++ b/gnu-efi/inc/efidebug.h @@ -0,0 +1,620 @@ +#ifndef _EFI_DEBUG_H +#define _EFI_DEBUG_H + +/*++ + +Copyright (c) 1998 Intel Corporation + +Module Name: + + efidebug.h + +Abstract: + + EFI library debug functions + + + +Revision History + +--*/ + +extern UINTN EFIDebug; + +#if EFI_DEBUG + + #define DBGASSERT(a) DbgAssert(__FILE__, __LINE__, #a) + #define DEBUG(a) DbgPrint a + +#else + + #define DBGASSERT(a) + #define DEBUG(a) + +#endif + +#if EFI_DEBUG_CLEAR_MEMORY + + #define DBGSETMEM(a,l) SetMem(a,l,(CHAR8)BAD_POINTER) + +#else + + #define DBGSETMEM(a,l) + +#endif + +#define D_INIT 0x00000001 // Initialization style messages +#define D_WARN 0x00000002 // Warnings +#define D_LOAD 0x00000004 // Load events +#define D_FS 0x00000008 // EFI File system +#define D_POOL 0x00000010 // Alloc & Free's +#define D_PAGE 0x00000020 // Alloc & Free's +#define D_INFO 0x00000040 // Verbose +#define D_VAR 0x00000100 // Variable +#define D_PARSE 0x00000200 // Command parsing +#define D_BM 0x00000400 // Boot manager +#define D_BLKIO 0x00001000 // BlkIo Driver +#define D_BLKIO_ULTRA 0x00002000 // BlkIo Driver +#define D_NET 0x00004000 // SNI Driver +#define D_NET_ULTRA 0x00008000 // SNI Driver +#define D_TXTIN 0x00010000 // Simple Input Driver +#define D_TXTOUT 0x00020000 // Simple Text Output Driver +#define D_ERROR_ATA 0x00040000 // ATA error messages +#define D_ERROR 0x80000000 // Error + +#define D_RESERVED 0x7fffC880 // Bits not reserved above + +// +// Current Debug level of the system, value of EFIDebug +// +//#define EFI_DBUG_MASK (D_ERROR | D_WARN | D_LOAD | D_BLKIO | D_INIT) +#define EFI_DBUG_MASK (D_ERROR) + +// +// +// + +#if EFI_DEBUG + + #define ASSERT(a) if(!(a)) DBGASSERT(a) + #define ASSERT_LOCKED(l) if(!(l)->Lock) DBGASSERT(l not locked) + #define ASSERT_STRUCT(p,t) DBGASSERT(t not structure), p + +#else + + #define ASSERT(a) + #define ASSERT_LOCKED(l) + #define ASSERT_STRUCT(p,t) + +#endif + +// +// Prototypes +// + +INTN +DbgAssert ( + CONST CHAR8 *file, + INTN lineno, + CONST CHAR8 *string + ); + +INTN +DbgPrint ( + INTN mask, + CONST CHAR8 *format, + ... + ); + +// +// Instruction Set Architectures definitions for debuggers +// + +typedef INTN EFI_EXCEPTION_TYPE; + +// IA32 +#define EXCEPT_IA32_DIVIDE_ERROR 0 +#define EXCEPT_IA32_DEBUG 1 +#define EXCEPT_IA32_NMI 2 +#define EXCEPT_IA32_BREAKPOINT 3 +#define EXCEPT_IA32_OVERFLOW 4 +#define EXCEPT_IA32_BOUND 5 +#define EXCEPT_IA32_INVALID_OPCODE 6 +#define EXCEPT_IA32_DOUBLE_FAULT 8 +#define EXCEPT_IA32_INVALID_TSS 10 +#define EXCEPT_IA32_SEG_NOT_PRESENT 11 +#define EXCEPT_IA32_STACK_FAULT 12 +#define EXCEPT_IA32_GP_FAULT 13 +#define EXCEPT_IA32_PAGE_FAULT 14 +#define EXCEPT_IA32_FP_ERROR 16 +#define EXCEPT_IA32_ALIGNMENT_CHECK 17 +#define EXCEPT_IA32_MACHINE_CHECK 18 +#define EXCEPT_IA32_SIMD 19 + +typedef struct { + UINT16 Fcw; + UINT16 Fsw; + UINT16 Ftw; + UINT16 Opcode; + UINT32 Eip; + UINT16 Cs; + UINT16 Reserved1; + UINT32 DataOffset; + UINT16 Ds; + UINT8 Reserved2[10]; + UINT8 St0Mm0[10], Reserved3[6]; + UINT8 St1Mm1[10], Reserved4[6]; + UINT8 St2Mm2[10], Reserved5[6]; + UINT8 St3Mm3[10], Reserved6[6]; + UINT8 St4Mm4[10], Reserved7[6]; + UINT8 St5Mm5[10], Reserved8[6]; + UINT8 St6Mm6[10], Reserved9[6]; + UINT8 St7Mm7[10], Reserved10[6]; + UINT8 Xmm0[16]; + UINT8 Xmm1[16]; + UINT8 Xmm2[16]; + UINT8 Xmm3[16]; + UINT8 Xmm4[16]; + UINT8 Xmm5[16]; + UINT8 Xmm6[16]; + UINT8 Xmm7[16]; + UINT8 Reserved11[14 * 16]; +} EFI_FX_SAVE_STATE_IA32; + +typedef struct { + UINT32 ExceptionData; + EFI_FX_SAVE_STATE_IA32 FxSaveState; + UINT32 Dr0; + UINT32 Dr1; + UINT32 Dr2; + UINT32 Dr3; + UINT32 Dr6; + UINT32 Dr7; + UINT32 Cr0; + UINT32 Cr1; + UINT32 Cr2; + UINT32 Cr3; + UINT32 Cr4; + UINT32 Eflags; + UINT32 Ldtr; + UINT32 Tr; + UINT32 Gdtr[2]; + UINT32 Idtr[2]; + UINT32 Eip; + UINT32 Gs; + UINT32 Fs; + UINT32 Es; + UINT32 Ds; + UINT32 Cs; + UINT32 Ss; + UINT32 Edi; + UINT32 Esi; + UINT32 Ebp; + UINT32 Esp; + UINT32 Ebx; + UINT32 Edx; + UINT32 Ecx; + UINT32 Eax; +} EFI_SYSTEM_CONTEXT_IA32; + +// X64 +#define EXCEPT_X64_DIVIDE_ERROR 0 +#define EXCEPT_X64_DEBUG 1 +#define EXCEPT_X64_NMI 2 +#define EXCEPT_X64_BREAKPOINT 3 +#define EXCEPT_X64_OVERFLOW 4 +#define EXCEPT_X64_BOUND 5 +#define EXCEPT_X64_INVALID_OPCODE 6 +#define EXCEPT_X64_DOUBLE_FAULT 8 +#define EXCEPT_X64_INVALID_TSS 10 +#define EXCEPT_X64_SEG_NOT_PRESENT 11 +#define EXCEPT_X64_STACK_FAULT 12 +#define EXCEPT_X64_GP_FAULT 13 +#define EXCEPT_X64_PAGE_FAULT 14 +#define EXCEPT_X64_FP_ERROR 16 +#define EXCEPT_X64_ALIGNMENT_CHECK 17 +#define EXCEPT_X64_MACHINE_CHECK 18 +#define EXCEPT_X64_SIMD 19 + +typedef struct { + UINT16 Fcw; + UINT16 Fsw; + UINT16 Ftw; + UINT16 Opcode; + UINT64 Rip; + UINT64 DataOffset; + UINT8 Reserved1[8]; + UINT8 St0Mm0[10], Reserved2[6]; + UINT8 St1Mm1[10], Reserved3[6]; + UINT8 St2Mm2[10], Reserved4[6]; + UINT8 St3Mm3[10], Reserved5[6]; + UINT8 St4Mm4[10], Reserved6[6]; + UINT8 St5Mm5[10], Reserved7[6]; + UINT8 St6Mm6[10], Reserved8[6]; + UINT8 St7Mm7[10], Reserved9[6]; + UINT8 Xmm0[16]; + UINT8 Xmm1[16]; + UINT8 Xmm2[16]; + UINT8 Xmm3[16]; + UINT8 Xmm4[16]; + UINT8 Xmm5[16]; + UINT8 Xmm6[16]; + UINT8 Xmm7[16]; + UINT8 Reserved11[14 * 16]; +} EFI_FX_SAVE_STATE_X64; + +typedef struct { + UINT64 ExceptionData; + EFI_FX_SAVE_STATE_X64 FxSaveState; + UINT64 Dr0; + UINT64 Dr1; + UINT64 Dr2; + UINT64 Dr3; + UINT64 Dr6; + UINT64 Dr7; + UINT64 Cr0; + UINT64 Cr1; + UINT64 Cr2; + UINT64 Cr3; + UINT64 Cr4; + UINT64 Cr8; + UINT64 Rflags; + UINT64 Ldtr; + UINT64 Tr; + UINT64 Gdtr[2]; + UINT64 Idtr[2]; + UINT64 Rip; + UINT64 Gs; + UINT64 Fs; + UINT64 Es; + UINT64 Ds; + UINT64 Cs; + UINT64 Ss; + UINT64 Rdi; + UINT64 Rsi; + UINT64 Rbp; + UINT64 Rsp; + UINT64 Rbx; + UINT64 Rdx; + UINT64 Rcx; + UINT64 Rax; + UINT64 R8; + UINT64 R9; + UINT64 R10; + UINT64 R11; + UINT64 R12; + UINT64 R13; + UINT64 R14; + UINT64 R15; +} EFI_SYSTEM_CONTEXT_X64; + +/// IA64 +#define EXCEPT_IPF_VHTP_TRANSLATION 0 +#define EXCEPT_IPF_INSTRUCTION_TLB 1 +#define EXCEPT_IPF_DATA_TLB 2 +#define EXCEPT_IPF_ALT_INSTRUCTION_TLB 3 +#define EXCEPT_IPF_ALT_DATA_TLB 4 +#define EXCEPT_IPF_DATA_NESTED_TLB 5 +#define EXCEPT_IPF_INSTRUCTION_KEY_MISSED 6 +#define EXCEPT_IPF_DATA_KEY_MISSED 7 +#define EXCEPT_IPF_DIRTY_BIT 8 +#define EXCEPT_IPF_INSTRUCTION_ACCESS_BIT 9 +#define EXCEPT_IPF_DATA_ACCESS_BIT 10 +#define EXCEPT_IPF_BREAKPOINT 11 +#define EXCEPT_IPF_EXTERNAL_INTERRUPT 12 +#define EXCEPT_IPF_PAGE_NOT_PRESENT 20 +#define EXCEPT_IPF_KEY_PERMISSION 21 +#define EXCEPT_IPF_INSTRUCTION_ACCESS_RIGHTS 22 +#define EXCEPT_IPF_DATA_ACCESS_RIGHTS 23 +#define EXCEPT_IPF_GENERAL_EXCEPTION 24 +#define EXCEPT_IPF_DISABLED_FP_REGISTER 25 +#define EXCEPT_IPF_NAT_CONSUMPTION 26 +#define EXCEPT_IPF_SPECULATION 27 +#define EXCEPT_IPF_DEBUG 29 +#define EXCEPT_IPF_UNALIGNED_REFERENCE 30 +#define EXCEPT_IPF_UNSUPPORTED_DATA_REFERENCE 31 +#define EXCEPT_IPF_FP_FAULT 32 +#define EXCEPT_IPF_FP_TRAP 33 +#define EXCEPT_IPF_LOWER_PRIVILEGE_TRANSFER_TRAP 34 +#define EXCEPT_IPF_TAKEN_BRANCH 35 +#define EXCEPT_IPF_SINGLE_STEP 36 +#define EXCEPT_IPF_IA32_EXCEPTION 45 +#define EXCEPT_IPF_IA32_INTERCEPT 46 +#define EXCEPT_IPF_IA32_INTERRUPT 47 + +typedef struct { + UINT64 Reserved; + UINT64 R1; + UINT64 R2; + UINT64 R3; + UINT64 R4; + UINT64 R5; + UINT64 R6; + UINT64 R7; + UINT64 R8; + UINT64 R9; + UINT64 R10; + UINT64 R11; + UINT64 R12; + UINT64 R13; + UINT64 R14; + UINT64 R15; + UINT64 R16; + UINT64 R17; + UINT64 R18; + UINT64 R19; + UINT64 R20; + UINT64 R21; + UINT64 R22; + UINT64 R23; + UINT64 R24; + UINT64 R25; + UINT64 R26; + UINT64 R27; + UINT64 R28; + UINT64 R29; + UINT64 R30; + UINT64 R31; + UINT64 F2[2]; + UINT64 F3[2]; + UINT64 F4[2]; + UINT64 F5[2]; + UINT64 F6[2]; + UINT64 F7[2]; + UINT64 F8[2]; + UINT64 F9[2]; + UINT64 F10[2]; + UINT64 F11[2]; + UINT64 F12[2]; + UINT64 F13[2]; + UINT64 F14[2]; + UINT64 F15[2]; + UINT64 F16[2]; + UINT64 F17[2]; + UINT64 F18[2]; + UINT64 F19[2]; + UINT64 F20[2]; + UINT64 F21[2]; + UINT64 F22[2]; + UINT64 F23[2]; + UINT64 F24[2]; + UINT64 F25[2]; + UINT64 F26[2]; + UINT64 F27[2]; + UINT64 F28[2]; + UINT64 F29[2]; + UINT64 F30[2]; + UINT64 F31[2]; + UINT64 Pr; + UINT64 B0; + UINT64 B1; + UINT64 B2; + UINT64 B3; + UINT64 B4; + UINT64 B5; + UINT64 B6; + UINT64 B7; + UINT64 ArRsc; + UINT64 ArBsp; + UINT64 ArBspstore; + UINT64 ArRnat; + UINT64 ArFcr; + UINT64 ArEflag; + UINT64 ArCsd; + UINT64 ArSsd; + UINT64 ArCflg; + UINT64 ArFsr; + UINT64 ArFir; + UINT64 ArFdr; + UINT64 ArCcv; + UINT64 ArUnat; + UINT64 ArFpsr; + UINT64 ArPfs; + UINT64 ArLc; + UINT64 ArEc; + UINT64 CrDcr; + UINT64 CrItm; + UINT64 CrIva; + UINT64 CrPta; + UINT64 CrIpsr; + UINT64 CrIsr; + UINT64 CrIip; + UINT64 CrIfa; + UINT64 CrItir; + UINT64 CrIipa; + UINT64 CrIfs; + UINT64 CrIim; + UINT64 CrIha; + UINT64 Dbr0; + UINT64 Dbr1; + UINT64 Dbr2; + UINT64 Dbr3; + UINT64 Dbr4; + UINT64 Dbr5; + UINT64 Dbr6; + UINT64 Dbr7; + UINT64 Ibr0; + UINT64 Ibr1; + UINT64 Ibr2; + UINT64 Ibr3; + UINT64 Ibr4; + UINT64 Ibr5; + UINT64 Ibr6; + UINT64 Ibr7; + UINT64 IntNat; +} EFI_SYSTEM_CONTEXT_IPF; + +// EBC +#define EXCEPT_EBC_UNDEFINED 0 +#define EXCEPT_EBC_DIVIDE_ERROR 1 +#define EXCEPT_EBC_DEBUG 2 +#define EXCEPT_EBC_BREAKPOINT 3 +#define EXCEPT_EBC_OVERFLOW 4 +#define EXCEPT_EBC_INVALID_OPCODE 5 +#define EXCEPT_EBC_STACK_FAULT 6 +#define EXCEPT_EBC_ALIGNMENT_CHECK 7 +#define EXCEPT_EBC_INSTRUCTION_ENCODING 8 +#define EXCEPT_EBC_BAD_BREAK 9 +#define EXCEPT_EBC_STEP 10 +#define MAX_EBC_EXCEPTION EXCEPT_EBC_STEP + +typedef struct { + UINT64 R0; + UINT64 R1; + UINT64 R2; + UINT64 R3; + UINT64 R4; + UINT64 R5; + UINT64 R6; + UINT64 R7; + UINT64 Flags; + UINT64 ControlFlags; + UINT64 Ip; +} EFI_SYSTEM_CONTEXT_EBC; + +// ARM +#define EXCEPT_ARM_RESET 0 +#define EXCEPT_ARM_UNDEFINED_INSTRUCTION 1 +#define EXCEPT_ARM_SOFTWARE_INTERRUPT 2 +#define EXCEPT_ARM_PREFETCH_ABORT 3 +#define EXCEPT_ARM_DATA_ABORT 4 +#define EXCEPT_ARM_RESERVED 5 +#define EXCEPT_ARM_IRQ 6 +#define EXCEPT_ARM_FIQ 7 +#define MAX_ARM_EXCEPTION EXCEPT_ARM_FIQ + +typedef struct { + UINT32 R0; + UINT32 R1; + UINT32 R2; + UINT32 R3; + UINT32 R4; + UINT32 R5; + UINT32 R6; + UINT32 R7; + UINT32 R8; + UINT32 R9; + UINT32 R10; + UINT32 R11; + UINT32 R12; + UINT32 SP; + UINT32 LR; + UINT32 PC; + UINT32 CPSR; + UINT32 DFSR; + UINT32 DFAR; + UINT32 IFSR; + UINT32 IFAR; +} EFI_SYSTEM_CONTEXT_ARM; + + +typedef union { + EFI_SYSTEM_CONTEXT_EBC *SystemContextEbc; + EFI_SYSTEM_CONTEXT_IA32 *SystemContextIa32; + EFI_SYSTEM_CONTEXT_X64 *SystemContextX64; + EFI_SYSTEM_CONTEXT_IPF *SystemContextIpf; + EFI_SYSTEM_CONTEXT_ARM *SystemContextArm; +} EFI_SYSTEM_CONTEXT; + +typedef +VOID +(EFIAPI *EFI_EXCEPTION_CALLBACK)( + IN EFI_EXCEPTION_TYPE ExceptionType, + IN OUT EFI_SYSTEM_CONTEXT SystemContext); + +typedef +VOID +(EFIAPI *EFI_PERIODIC_CALLBACK)( + IN OUT EFI_SYSTEM_CONTEXT SystemContext); + +typedef enum { + IsaIa32 = EFI_IMAGE_MACHINE_IA32, + IsaX64 = EFI_IMAGE_MACHINE_X64, + IsaIpf = EFI_IMAGE_MACHINE_IA64, + IsaEbc = EFI_IMAGE_MACHINE_EBC, + IsaArm = EFI_IMAGE_MACHINE_ARMTHUMB_MIXED, +// IsaArm64 = EFI_IMAGE_MACHINE_AARCH64 +} EFI_INSTRUCTION_SET_ARCHITECTURE; + +// +// DEBUG_IMAGE_INFO +// + +#define EFI_DEBUG_IMAGE_INFO_TABLE_GUID \ + { 0x49152e77, 0x1ada, 0x4764, {0xb7, 0xa2, 0x7a, 0xfe, 0xfe, 0xd9, 0x5e, 0x8b} } + +#define EFI_DEBUG_IMAGE_INFO_UPDATE_IN_PROGRESS 0x01 +#define EFI_DEBUG_IMAGE_INFO_TABLE_MODIFIED 0x02 +#define EFI_DEBUG_IMAGE_INFO_INITIAL_SIZE (EFI_PAGE_SIZE / sizeof (UINTN)) +#define EFI_DEBUG_IMAGE_INFO_TYPE_NORMAL 0x01 + +typedef struct { +UINT64 Signature; +EFI_PHYSICAL_ADDRESS EfiSystemTableBase; +UINT32 Crc32; +} EFI_SYSTEM_TABLE_POINTER; + +typedef struct { +UINT32 ImageInfoType; +EFI_LOADED_IMAGE_PROTOCOL *LoadedImageProtocolInstance; +EFI_HANDLE *ImageHandle; +} EFI_DEBUG_IMAGE_INFO_NORMAL; + +typedef union { +UINT32 *ImageInfoType; +EFI_DEBUG_IMAGE_INFO_NORMAL *NormalImage; +} EFI_DEBUG_IMAGE_INFO; + +typedef struct { +volatile UINT32 UpdateStatus; +UINT32 TableSize; +EFI_DEBUG_IMAGE_INFO *EfiDebugImageInfoTable; +} EFI_DEBUG_IMAGE_INFO_TABLE_HEADER; + +// +// EFI_DEBUGGER_PROTOCOL +// + +#define EFI_DEBUG_SUPPORT_PROTOCOL_GUID \ + { 0x2755590c, 0x6f3c, 0x42fa, {0x9e, 0xa4, 0xa3, 0xba, 0x54, 0x3c, 0xda, 0x25} } + +INTERFACE_DECL(_EFI_DEBUG_SUPPORT_PROTOCOL); + +typedef +EFI_STATUS +(EFIAPI *EFI_GET_MAXIMUM_PROCESSOR_INDEX)( + IN struct _EFI_DEBUG_SUPPORT_PROTOCOL *This, + OUT UINTN *MaxProcessorIndex); + +typedef +EFI_STATUS +(EFIAPI *EFI_REGISTER_PERIODIC_CALLBACK)( + IN struct _EFI_DEBUG_SUPPORT_PROTOCOL *This, + IN UINTN ProcessorIndex, + IN EFI_PERIODIC_CALLBACK PeriodicCallback); + +typedef +EFI_STATUS +(EFIAPI *EFI_REGISTER_EXCEPTION_CALLBACK)( + IN struct _EFI_DEBUG_SUPPORT_PROTOCOL *This, + IN UINTN ProcessorIndex, + IN EFI_EXCEPTION_CALLBACK ExceptionCallback, + IN EFI_EXCEPTION_TYPE ExceptionType); + +typedef +EFI_STATUS +(EFIAPI *EFI_INVALIDATE_INSTRUCTION_CACHE)( + IN struct _EFI_DEBUG_SUPPORT_PROTOCOL *This, + IN UINTN ProcessorIndex, + IN VOID *Start, + IN UINT64 Length); + +typedef struct _EFI_DEBUG_SUPPORT_PROTOCOL { + EFI_INSTRUCTION_SET_ARCHITECTURE Isa; + EFI_GET_MAXIMUM_PROCESSOR_INDEX GetMaximumProcessorIndex; + EFI_REGISTER_PERIODIC_CALLBACK RegisterPeriodicCallback; + EFI_REGISTER_EXCEPTION_CALLBACK RegisterExceptionCallback; + EFI_INVALIDATE_INSTRUCTION_CACHE InvalidateInstructionCache; +} EFI_DEBUG_SUPPORT_PROTOCOL; + +#endif diff --git a/gnu-efi/inc/efidef.h b/gnu-efi/inc/efidef.h new file mode 100644 index 0000000..8b70051 --- /dev/null +++ b/gnu-efi/inc/efidef.h @@ -0,0 +1,220 @@ +#ifndef _EFI_DEF_H +#define _EFI_DEF_H + +/*++ + +Copyright (c) 1998 Intel Corporation + +Module Name: + + efidef.h + +Abstract: + + EFI definitions + + + + +Revision History + +--*/ + +typedef UINT16 CHAR16; +typedef UINT8 CHAR8; +typedef UINT8 BOOLEAN; +#ifndef CONST + #define CONST const +#endif +#ifndef TRUE + #define TRUE ((BOOLEAN) 1) + #define FALSE ((BOOLEAN) 0) +#endif + +#ifndef NULL + #define NULL ((VOID *) 0) +#endif + +typedef UINTN EFI_STATUS; +typedef UINT64 EFI_LBA; +typedef UINTN EFI_TPL; +typedef VOID *EFI_HANDLE; +typedef VOID *EFI_EVENT; + + +// +// Prototype argument decoration for EFI parameters to indicate +// their direction +// +// IN - argument is passed into the function +// OUT - argument (pointer) is returned from the function +// OPTIONAL - argument is optional +// + +#ifndef IN + #define IN + #define OUT + #define OPTIONAL +#endif + + +// +// A GUID +// + +typedef struct { + UINT32 Data1; + UINT16 Data2; + UINT16 Data3; + UINT8 Data4[8]; +} EFI_GUID; + + +// +// Time +// + +typedef struct { + UINT16 Year; // 1998 - 20XX + UINT8 Month; // 1 - 12 + UINT8 Day; // 1 - 31 + UINT8 Hour; // 0 - 23 + UINT8 Minute; // 0 - 59 + UINT8 Second; // 0 - 59 + UINT8 Pad1; + UINT32 Nanosecond; // 0 - 999,999,999 + INT16 TimeZone; // -1440 to 1440 or 2047 + UINT8 Daylight; + UINT8 Pad2; +} EFI_TIME; + +// Bit definitions for EFI_TIME.Daylight +#define EFI_TIME_ADJUST_DAYLIGHT 0x01 +#define EFI_TIME_IN_DAYLIGHT 0x02 + +// Value definition for EFI_TIME.TimeZone +#define EFI_UNSPECIFIED_TIMEZONE 0x07FF + + + +// +// Networking +// + +typedef struct { + UINT8 Addr[4]; +} EFI_IPv4_ADDRESS; + +typedef struct { + UINT8 Addr[16]; +} EFI_IPv6_ADDRESS; + +typedef struct { + UINT8 Addr[32]; +} EFI_MAC_ADDRESS; + +typedef struct { + UINT32 ReceivedQueueTimeoutValue; + UINT32 TransmitQueueTimeoutValue; + UINT16 ProtocolTypeFilter; + BOOLEAN EnableUnicastReceive; + BOOLEAN EnableMulticastReceive; + BOOLEAN EnableBroadcastReceive; + BOOLEAN EnablePromiscuousReceive; + BOOLEAN FlushQueuesOnReset; + BOOLEAN EnableReceiveTimestamps; + BOOLEAN DisableBackgroundPolling; +} EFI_MANAGED_NETWORK_CONFIG_DATA; + +// +// Memory +// + +typedef UINT64 EFI_PHYSICAL_ADDRESS; +typedef UINT64 EFI_VIRTUAL_ADDRESS; + +typedef enum { + AllocateAnyPages, + AllocateMaxAddress, + AllocateAddress, + MaxAllocateType +} EFI_ALLOCATE_TYPE; + +//Preseve the attr on any range supplied. +//ConventialMemory must have WB,SR,SW when supplied. +//When allocating from ConventialMemory always make it WB,SR,SW +//When returning to ConventialMemory always make it WB,SR,SW +//When getting the memory map, or on RT for runtime types + + +typedef enum { + EfiReservedMemoryType, + EfiLoaderCode, + EfiLoaderData, + EfiBootServicesCode, + EfiBootServicesData, + EfiRuntimeServicesCode, + EfiRuntimeServicesData, + EfiConventionalMemory, + EfiUnusableMemory, + EfiACPIReclaimMemory, + EfiACPIMemoryNVS, + EfiMemoryMappedIO, + EfiMemoryMappedIOPortSpace, + EfiPalCode, + EfiMaxMemoryType +} EFI_MEMORY_TYPE; + +// possible caching types for the memory range +#define EFI_MEMORY_UC 0x0000000000000001 +#define EFI_MEMORY_WC 0x0000000000000002 +#define EFI_MEMORY_WT 0x0000000000000004 +#define EFI_MEMORY_WB 0x0000000000000008 +#define EFI_MEMORY_UCE 0x0000000000000010 + +// physical memory protection on range +#define EFI_MEMORY_WP 0x0000000000001000 +#define EFI_MEMORY_RP 0x0000000000002000 +#define EFI_MEMORY_XP 0x0000000000004000 + +// range requires a runtime mapping +#define EFI_MEMORY_RUNTIME 0x8000000000000000 + +#define EFI_MEMORY_DESCRIPTOR_VERSION 1 +typedef struct { + UINT32 Type; // Field size is 32 bits followed by 32 bit pad + UINT32 Pad; + EFI_PHYSICAL_ADDRESS PhysicalStart; // Field size is 64 bits + EFI_VIRTUAL_ADDRESS VirtualStart; // Field size is 64 bits + UINT64 NumberOfPages; // Field size is 64 bits + UINT64 Attribute; // Field size is 64 bits +} EFI_MEMORY_DESCRIPTOR; + +// +// International Language +// + +typedef UINT8 ISO_639_2; +#define ISO_639_2_ENTRY_SIZE 3 + +// +// +// + +#define EFI_PAGE_SIZE 4096 +#define EFI_PAGE_MASK 0xFFF +#define EFI_PAGE_SHIFT 12 + +#define EFI_SIZE_TO_PAGES(a) \ + ( ((a) >> EFI_PAGE_SHIFT) + ((a) & EFI_PAGE_MASK ? 1 : 0) ) + +#define EFI_OS_INDICATIONS_BOOT_TO_FW_UI 0x0000000000000001 +#define EFI_OS_INDICATIONS_TIMESTAMP_REVOCATION 0x0000000000000002 +#define EFI_OS_INDICATIONS_FILE_CAPSULE_DELIVERY_SUPPORTED \ + 0x0000000000000004 +#define EFI_OS_INDICATIONS_FMP_CAPSULE_SUPPORTED \ + 0x0000000000000008 +#define EFI_OS_INDICATIONS_CAPSULE_RESULT_VAR_SUPPORTED \ + 0x0000000000000010 + +#endif diff --git a/gnu-efi/inc/efidevp.h b/gnu-efi/inc/efidevp.h new file mode 100644 index 0000000..fa1a235 --- /dev/null +++ b/gnu-efi/inc/efidevp.h @@ -0,0 +1,582 @@ +#ifndef _DEVPATH_H +#define _DEVPATH_H + +/*++ + +Copyright (c) 1998 Intel Corporation + +Module Name: + + devpath.h + +Abstract: + + Defines for parsing the EFI Device Path structures + + + +Revision History + +--*/ + +// +// Device Path structures - Section C +// + +typedef struct _EFI_DEVICE_PATH_PROTOCOL { + UINT8 Type; + UINT8 SubType; + UINT8 Length[2]; +} EFI_DEVICE_PATH_PROTOCOL; + +typedef struct _EFI_DEVICE_PATH_PROTOCOL _EFI_DEVICE_PATH; +typedef EFI_DEVICE_PATH_PROTOCOL EFI_DEVICE_PATH; + +#define EFI_DP_TYPE_MASK 0x7F +#define EFI_DP_TYPE_UNPACKED 0x80 + +//#define END_DEVICE_PATH_TYPE 0xff +#define END_DEVICE_PATH_TYPE 0x7f +//#define END_DEVICE_PATH_TYPE_UNPACKED 0x7f + +#define END_ENTIRE_DEVICE_PATH_SUBTYPE 0xff +#define END_INSTANCE_DEVICE_PATH_SUBTYPE 0x01 +#define END_DEVICE_PATH_LENGTH (sizeof(EFI_DEVICE_PATH_PROTOCOL)) + + +#define DP_IS_END_TYPE(a) +#define DP_IS_END_SUBTYPE(a) ( ((a)->SubType == END_ENTIRE_DEVICE_PATH_SUBTYPE ) + +#define DevicePathType(a) ( ((a)->Type) & EFI_DP_TYPE_MASK ) +#define DevicePathSubType(a) ( (a)->SubType ) +#define DevicePathNodeLength(a) ( ((a)->Length[0]) | ((a)->Length[1] << 8) ) +#define NextDevicePathNode(a) ( (EFI_DEVICE_PATH_PROTOCOL *) ( ((UINT8 *) (a)) + DevicePathNodeLength(a))) +//#define IsDevicePathEndType(a) ( DevicePathType(a) == END_DEVICE_PATH_TYPE_UNPACKED ) +#define IsDevicePathEndType(a) ( DevicePathType(a) == END_DEVICE_PATH_TYPE ) +#define IsDevicePathEndSubType(a) ( (a)->SubType == END_ENTIRE_DEVICE_PATH_SUBTYPE ) +#define IsDevicePathEnd(a) ( IsDevicePathEndType(a) && IsDevicePathEndSubType(a) ) +#define IsDevicePathUnpacked(a) ( (a)->Type & EFI_DP_TYPE_UNPACKED ) + + +#define SetDevicePathNodeLength(a,l) { \ + (a)->Length[0] = (UINT8) (l); \ + (a)->Length[1] = (UINT8) ((l) >> 8); \ + } + +#define SetDevicePathEndNode(a) { \ + (a)->Type = END_DEVICE_PATH_TYPE; \ + (a)->SubType = END_ENTIRE_DEVICE_PATH_SUBTYPE; \ + (a)->Length[0] = sizeof(EFI_DEVICE_PATH_PROTOCOL); \ + (a)->Length[1] = 0; \ + } + + +/* + * Hardware Device Path (UEFI 2.4 specification, version 2.4 § 9.3.2.) + */ + +#define HARDWARE_DEVICE_PATH 0x01 + +#define HW_PCI_DP 0x01 +typedef struct _PCI_DEVICE_PATH { + EFI_DEVICE_PATH_PROTOCOL Header; + UINT8 Function; + UINT8 Device; +} PCI_DEVICE_PATH; + +#define HW_PCCARD_DP 0x02 +typedef struct _PCCARD_DEVICE_PATH { + EFI_DEVICE_PATH_PROTOCOL Header; + UINT8 FunctionNumber ; +} PCCARD_DEVICE_PATH; + +#define HW_MEMMAP_DP 0x03 +typedef struct _MEMMAP_DEVICE_PATH { + EFI_DEVICE_PATH_PROTOCOL Header; + UINT32 MemoryType; + EFI_PHYSICAL_ADDRESS StartingAddress; + EFI_PHYSICAL_ADDRESS EndingAddress; +} MEMMAP_DEVICE_PATH; + +#define HW_VENDOR_DP 0x04 +typedef struct _VENDOR_DEVICE_PATH { + EFI_DEVICE_PATH_PROTOCOL Header; + EFI_GUID Guid; +} VENDOR_DEVICE_PATH; + +#define UNKNOWN_DEVICE_GUID \ + { 0xcf31fac5, 0xc24e, 0x11d2, {0x85, 0xf3, 0x0, 0xa0, 0xc9, 0x3e, 0xc9, 0x3b} } + +typedef struct _UKNOWN_DEVICE_VENDOR_DP { + VENDOR_DEVICE_PATH DevicePath; + UINT8 LegacyDriveLetter; +} UNKNOWN_DEVICE_VENDOR_DEVICE_PATH; + +#define HW_CONTROLLER_DP 0x05 +typedef struct _CONTROLLER_DEVICE_PATH { + EFI_DEVICE_PATH_PROTOCOL Header; + UINT32 Controller; +} CONTROLLER_DEVICE_PATH; + + +/* + * ACPI Device Path (UEFI 2.4 specification, version 2.4 § 9.3.3 and 9.3.4.) + */ +#define ACPI_DEVICE_PATH 0x02 + +#define ACPI_DP 0x01 +typedef struct _ACPI_HID_DEVICE_PATH { + EFI_DEVICE_PATH_PROTOCOL Header; + UINT32 HID; + UINT32 UID; +} ACPI_HID_DEVICE_PATH; + +#define EXPANDED_ACPI_DP 0x02 +typedef struct _EXPANDED_ACPI_HID_DEVICE_PATH { + EFI_DEVICE_PATH_PROTOCOL Header; + UINT32 HID; + UINT32 UID; + UINT32 CID; + UINT8 HidStr[1]; +} EXPANDED_ACPI_HID_DEVICE_PATH; + +#define ACPI_ADR_DP 3 +typedef struct _ACPI_ADR_DEVICE_PATH { + EFI_DEVICE_PATH_PROTOCOL Header ; + UINT32 ADR ; +} ACPI_ADR_DEVICE_PATH ; + +// +// EISA ID Macro +// EISA ID Definition 32-bits +// bits[15:0] - three character compressed ASCII EISA ID. +// bits[31:16] - binary number +// Compressed ASCII is 5 bits per character 0b00001 = 'A' 0b11010 = 'Z' +// +#define PNP_EISA_ID_CONST 0x41d0 +#define EISA_ID(_Name, _Num) ((UINT32) ((_Name) | (_Num) << 16)) +#define EISA_PNP_ID(_PNPId) (EISA_ID(PNP_EISA_ID_CONST, (_PNPId))) + +#define PNP_EISA_ID_MASK 0xffff +#define EISA_ID_TO_NUM(_Id) ((_Id) >> 16) + + +/* + * Messaging Device Path (UEFI 2.4 specification, version 2.4 § 9.3.5.) + */ +#define MESSAGING_DEVICE_PATH 0x03 + +#define MSG_ATAPI_DP 0x01 +typedef struct _ATAPI_DEVICE_PATH { + EFI_DEVICE_PATH_PROTOCOL Header; + UINT8 PrimarySecondary; + UINT8 SlaveMaster; + UINT16 Lun; +} ATAPI_DEVICE_PATH; + +#define MSG_SCSI_DP 0x02 +typedef struct _SCSI_DEVICE_PATH { + EFI_DEVICE_PATH_PROTOCOL Header; + UINT16 Pun; + UINT16 Lun; +} SCSI_DEVICE_PATH; + +#define MSG_FIBRECHANNEL_DP 0x03 +typedef struct _FIBRECHANNEL_DEVICE_PATH { + EFI_DEVICE_PATH_PROTOCOL Header; + UINT32 Reserved; + UINT64 WWN; + UINT64 Lun; +} FIBRECHANNEL_DEVICE_PATH; + +/** + * Fibre Channel Ex SubType. + * UEFI 2.0 specification version 2.4 § 9.3.5.6. + */ +#define MSG_FIBRECHANNELEX_DP 21 +typedef struct _FIBRECHANNELEX_DEVICE_PATH { + EFI_DEVICE_PATH_PROTOCOL Header ; + UINT32 Reserved ; + UINT8 WWN[ 8 ] ; /* World Wide Name */ + UINT8 Lun[ 8 ] ; /* Logical unit, T-10 SCSI Architecture Model 4 specification */ +} FIBRECHANNELEX_DEVICE_PATH ; + +#define MSG_1394_DP 0x04 +typedef struct _F1394_DEVICE_PATH { + EFI_DEVICE_PATH_PROTOCOL Header; + UINT32 Reserved; + UINT64 Guid; +} F1394_DEVICE_PATH; + +#define MSG_USB_DP 0x05 +typedef struct _USB_DEVICE_PATH { + EFI_DEVICE_PATH_PROTOCOL Header; + UINT8 Port; + UINT8 Endpoint; +} USB_DEVICE_PATH; + +/** + * SATA Device Path SubType. + * UEFI 2.0 specification version 2.4 § 9.3.5.6. + */ +#define MSG_SATA_DP 18 +typedef struct _SATA_DEVICE_PATH { + EFI_DEVICE_PATH_PROTOCOL Header ; + UINT16 HBAPortNumber ; + UINT16 PortMultiplierPortNumber ; + UINT16 Lun ; /* Logical Unit Number */ +} SATA_DEVICE_PATH ; + +/** + * USB WWID Device Path SubType. + * UEFI 2.0 specification version 2.4 § 9.3.5.7. + */ +#define MSG_USB_WWID_DP 16 +typedef struct _USB_WWID_DEVICE_PATH { + EFI_DEVICE_PATH_PROTOCOL Header ; + UINT16 InterfaceNumber ; + UINT16 VendorId ; + UINT16 ProductId ; + CHAR16 SerialNumber[ 1 ] ; /* UTF-16 characters of the USB serial number */ +} USB_WWID_DEVICE_PATH ; + +/** + * Device Logical Unit SubType. + * UEFI 2.0 specification version 2.4 § 9.3.5.8. + */ +#define MSG_DEVICE_LOGICAL_UNIT_DP 17 +typedef struct _DEVICE_LOGICAL_UNIT_DEVICE_PATH { + EFI_DEVICE_PATH_PROTOCOL Header ; + UINT8 Lun ; /* Logical Unit Number */ +} DEVICE_LOGICAL_UNIT_DEVICE_PATH ; + +#define MSG_USB_CLASS_DP 0x0F +typedef struct _USB_CLASS_DEVICE_PATH { + EFI_DEVICE_PATH_PROTOCOL Header; + UINT16 VendorId; + UINT16 ProductId; + UINT8 DeviceClass; + UINT8 DeviceSubclass; + UINT8 DeviceProtocol; +} USB_CLASS_DEVICE_PATH; + +#define MSG_I2O_DP 0x06 +typedef struct _I2O_DEVICE_PATH { + EFI_DEVICE_PATH_PROTOCOL Header; + UINT32 Tid; +} I2O_DEVICE_PATH; + +#define MSG_MAC_ADDR_DP 0x0b +typedef struct _MAC_ADDR_DEVICE_PATH { + EFI_DEVICE_PATH_PROTOCOL Header; + EFI_MAC_ADDRESS MacAddress; + UINT8 IfType; +} MAC_ADDR_DEVICE_PATH; + +#define MSG_IPv4_DP 0x0c +typedef struct _IPv4_DEVICE_PATH { + EFI_DEVICE_PATH_PROTOCOL Header; + EFI_IPv4_ADDRESS LocalIpAddress; + EFI_IPv4_ADDRESS RemoteIpAddress; + UINT16 LocalPort; + UINT16 RemotePort; + UINT16 Protocol; + BOOLEAN StaticIpAddress; + /* new from UEFI version 2, code must check Length field in Header */ + EFI_IPv4_ADDRESS GatewayIpAddress ; + EFI_IPv4_ADDRESS SubnetMask ; +} IPv4_DEVICE_PATH; + +#define MSG_IPv6_DP 0x0d +typedef struct _IPv6_DEVICE_PATH { + EFI_DEVICE_PATH_PROTOCOL Header; + EFI_IPv6_ADDRESS LocalIpAddress; + EFI_IPv6_ADDRESS RemoteIpAddress; + UINT16 LocalPort; + UINT16 RemotePort; + UINT16 Protocol; + BOOLEAN IPAddressOrigin ; + /* new from UEFI version 2, code must check Length field in Header */ + UINT8 PrefixLength ; + EFI_IPv6_ADDRESS GatewayIpAddress ; +} IPv6_DEVICE_PATH; + + +/** + * Uniform Resource Identifiers SubType. + * UEFI 2.0 specification version 2.4C § 9.3.5.23. + */ +#define MSG_URI_DP 24 +typedef struct _URI_DEVICE_PATH { + EFI_DEVICE_PATH_PROTOCOL Header; + CHAR8 Uri[1]; +} URI_DEVICE_PATH; + +/** + * Device Logical Unit SubType. + * UEFI 2.0 specification version 2.4 § 9.3.5.8. + */ +#define MSG_VLAN_DP 20 +typedef struct _VLAN_DEVICE_PATH { + EFI_DEVICE_PATH_PROTOCOL Header ; + UINT16 VlanId ; +} VLAN_DEVICE_PATH; + +#define MSG_INFINIBAND_DP 0x09 +typedef struct _INFINIBAND_DEVICE_PATH { + EFI_DEVICE_PATH_PROTOCOL Header; + UINT32 ResourceFlags; + UINT8 PortGid[16]; + UINT64 ServiceId; + UINT64 TargetPortId; + UINT64 DeviceId; +} INFINIBAND_DEVICE_PATH; + +#define MSG_UART_DP 0x0e +typedef struct _UART_DEVICE_PATH { + EFI_DEVICE_PATH_PROTOCOL Header; + UINT32 Reserved; + UINT64 BaudRate; + UINT8 DataBits; + UINT8 Parity; + UINT8 StopBits; +} UART_DEVICE_PATH; + +#define MSG_VENDOR_DP 0x0A +/* Use VENDOR_DEVICE_PATH struct */ + +#define EFI_PC_ANSI_GUID \ + { 0xe0c14753, 0xf9be, 0x11d2, {0x9a, 0x0c, 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d} } +#define DEVICE_PATH_MESSAGING_PC_ANSI EFI_PC_ANSI_GUID + +#define EFI_VT_100_GUID \ + { 0xdfa66065, 0xb419, 0x11d3, {0x9a, 0x2d, 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d} } +#define DEVICE_PATH_MESSAGING_VT_100 EFI_VT_100_GUID + +#define EFI_VT_100_PLUS_GUID \ + { 0x7baec70b, 0x57e0, 0x4c76, {0x8e, 0x87, 0x2f, 0x9e, 0x28, 0x08, 0x83, 0x43} } +#define DEVICE_PATH_MESSAGING_VT_100_PLUS EFI_VT_100_PLUS_GUID + +#define EFI_VT_UTF8_GUID \ + { 0xad15a0d6, 0x8bec, 0x4acf, {0xa0, 0x73, 0xd0, 0x1d, 0xe7, 0x7e, 0x2d, 0x88} } +#define DEVICE_PATH_MESSAGING_VT_UTF8 EFI_VT_UTF8_GUID + + +/* + * Media Device Path (UEFI 2.4 specification, version 2.4 § 9.3.6.) + */ +#define MEDIA_DEVICE_PATH 0x04 + +#define MEDIA_HARDDRIVE_DP 0x01 +typedef struct _HARDDRIVE_DEVICE_PATH { + EFI_DEVICE_PATH_PROTOCOL Header; + UINT32 PartitionNumber; + UINT64 PartitionStart; + UINT64 PartitionSize; + UINT8 Signature[16]; + UINT8 MBRType; + UINT8 SignatureType; +} HARDDRIVE_DEVICE_PATH; + +#define MBR_TYPE_PCAT 0x01 +#define MBR_TYPE_EFI_PARTITION_TABLE_HEADER 0x02 + +#define SIGNATURE_TYPE_MBR 0x01 +#define SIGNATURE_TYPE_GUID 0x02 + +#define MEDIA_CDROM_DP 0x02 +typedef struct _CDROM_DEVICE_PATH { + EFI_DEVICE_PATH_PROTOCOL Header; + UINT32 BootEntry; + UINT64 PartitionStart; + UINT64 PartitionSize; +} CDROM_DEVICE_PATH; + +#define MEDIA_VENDOR_DP 0x03 +/* Use VENDOR_DEVICE_PATH struct */ + +#define MEDIA_FILEPATH_DP 0x04 +typedef struct _FILEPATH_DEVICE_PATH { + EFI_DEVICE_PATH_PROTOCOL Header; + CHAR16 PathName[1]; +} FILEPATH_DEVICE_PATH; + +#define SIZE_OF_FILEPATH_DEVICE_PATH EFI_FIELD_OFFSET(FILEPATH_DEVICE_PATH,PathName) + +#define MEDIA_PROTOCOL_DP 0x05 +typedef struct _MEDIA_PROTOCOL_DEVICE_PATH { + EFI_DEVICE_PATH_PROTOCOL Header; + EFI_GUID Protocol; +} MEDIA_PROTOCOL_DEVICE_PATH; + +/** + * PIWG Firmware File SubType. + * UEFI 2.0 specification version 2.4 § 9.3.6.6. + */ +#define MEDIA_PIWG_FW_FILE_DP 6 +typedef struct _MEDIA_FW_VOL_FILEPATH_DEVICE_PATH { + EFI_DEVICE_PATH_PROTOCOL Header ; + EFI_GUID FvFileName ; +} MEDIA_FW_VOL_FILEPATH_DEVICE_PATH ; + +/** + * PIWG Firmware Volume Device Path SubType. + * UEFI 2.0 specification version 2.4 § 9.3.6.7. + */ +#define MEDIA_PIWG_FW_VOL_DP 7 +typedef struct _MEDIA_FW_VOL_DEVICE_PATH { + EFI_DEVICE_PATH_PROTOCOL Header ; + EFI_GUID FvName ; +} MEDIA_FW_VOL_DEVICE_PATH ; + +/** + * Media relative offset range device path. + * UEFI 2.0 specification version 2.4 § 9.3.6.8. + */ +#define MEDIA_RELATIVE_OFFSET_RANGE_DP 8 +typedef struct _MEDIA_RELATIVE_OFFSET_RANGE_DEVICE_PATH { + EFI_DEVICE_PATH_PROTOCOL Header ; + UINT32 Reserved ; + UINT64 StartingOffset ; + UINT64 EndingOffset ; +} MEDIA_RELATIVE_OFFSET_RANGE_DEVICE_PATH ; + + +/* + * BIOS Boot Specification Device Path (UEFI 2.4 specification, version 2.4 § 9.3.7.) + */ +#define BBS_DEVICE_PATH 0x05 + +#define BBS_BBS_DP 0x01 +typedef struct _BBS_BBS_DEVICE_PATH { + EFI_DEVICE_PATH_PROTOCOL Header; + UINT16 DeviceType; + UINT16 StatusFlag; + CHAR8 String[1]; +} BBS_BBS_DEVICE_PATH; + +/* DeviceType definitions - from BBS specification */ +#define BBS_TYPE_FLOPPY 0x01 +#define BBS_TYPE_HARDDRIVE 0x02 +#define BBS_TYPE_CDROM 0x03 +#define BBS_TYPE_PCMCIA 0x04 +#define BBS_TYPE_USB 0x05 +#define BBS_TYPE_EMBEDDED_NETWORK 0x06 +#define BBS_TYPE_DEV 0x80 +#define BBS_TYPE_UNKNOWN 0xFF + +typedef union { + EFI_DEVICE_PATH_PROTOCOL DevPath; + PCI_DEVICE_PATH Pci; + PCCARD_DEVICE_PATH PcCard; + MEMMAP_DEVICE_PATH MemMap; + VENDOR_DEVICE_PATH Vendor; + UNKNOWN_DEVICE_VENDOR_DEVICE_PATH UnknownVendor; + CONTROLLER_DEVICE_PATH Controller; + ACPI_HID_DEVICE_PATH Acpi; + + ATAPI_DEVICE_PATH Atapi; + SCSI_DEVICE_PATH Scsi; + FIBRECHANNEL_DEVICE_PATH FibreChannel; + + F1394_DEVICE_PATH F1394; + USB_DEVICE_PATH Usb; + USB_CLASS_DEVICE_PATH UsbClass; + I2O_DEVICE_PATH I2O; + MAC_ADDR_DEVICE_PATH MacAddr; + IPv4_DEVICE_PATH Ipv4; + IPv6_DEVICE_PATH Ipv6; + URI_DEVICE_PATH Uri; + INFINIBAND_DEVICE_PATH InfiniBand; + UART_DEVICE_PATH Uart; + + HARDDRIVE_DEVICE_PATH HardDrive; + CDROM_DEVICE_PATH CD; + + FILEPATH_DEVICE_PATH FilePath; + MEDIA_PROTOCOL_DEVICE_PATH MediaProtocol; + + BBS_BBS_DEVICE_PATH Bbs; + +} EFI_DEV_PATH; + +typedef union { + EFI_DEVICE_PATH_PROTOCOL *DevPath; + PCI_DEVICE_PATH *Pci; + PCCARD_DEVICE_PATH *PcCard; + MEMMAP_DEVICE_PATH *MemMap; + VENDOR_DEVICE_PATH *Vendor; + UNKNOWN_DEVICE_VENDOR_DEVICE_PATH *UnknownVendor; + CONTROLLER_DEVICE_PATH *Controller; + ACPI_HID_DEVICE_PATH *Acpi; + + ATAPI_DEVICE_PATH *Atapi; + SCSI_DEVICE_PATH *Scsi; + FIBRECHANNEL_DEVICE_PATH *FibreChannel; + + F1394_DEVICE_PATH *F1394; + USB_DEVICE_PATH *Usb; + USB_CLASS_DEVICE_PATH *UsbClass; + I2O_DEVICE_PATH *I2O; + MAC_ADDR_DEVICE_PATH *MacAddr; + IPv4_DEVICE_PATH *Ipv4; + IPv6_DEVICE_PATH *Ipv6; + URI_DEVICE_PATH *Uri; + INFINIBAND_DEVICE_PATH *InfiniBand; + UART_DEVICE_PATH *Uart; + + HARDDRIVE_DEVICE_PATH *HardDrive; + + FILEPATH_DEVICE_PATH *FilePath; + MEDIA_PROTOCOL_DEVICE_PATH *MediaProtocol; + + CDROM_DEVICE_PATH *CD; + BBS_BBS_DEVICE_PATH *Bbs; + +} EFI_DEV_PATH_PTR; + +#define EFI_DEVICE_PATH_TO_TEXT_PROTOCOL_GUID \ + { 0x8b843e20, 0x8132, 0x4852, {0x90, 0xcc, 0x55, 0x1a, 0x4e, 0x4a, 0x7f, 0x1c} } + +typedef +CHAR16* +(EFIAPI *EFI_DEVICE_PATH_TO_TEXT_NODE) ( + IN CONST EFI_DEVICE_PATH_PROTOCOL *DeviceNode, + IN BOOLEAN DisplayOnly, + IN BOOLEAN AllowShortcuts + ); + +typedef +CHAR16* +(EFIAPI *EFI_DEVICE_PATH_TO_TEXT_PATH) ( + IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath, + IN BOOLEAN DisplayOnly, + IN BOOLEAN AllowShortcuts + ); + +typedef struct _EFI_DEVICE_PATH_TO_TEXT_PROTOCOL { + EFI_DEVICE_PATH_TO_TEXT_NODE ConvertDeviceNodeToText; + EFI_DEVICE_PATH_TO_TEXT_PATH ConvertDevicePathToText; +} EFI_DEVICE_PATH_TO_TEXT_PROTOCOL; + +#define EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL_GUID \ + { 0x5c99a21, 0xc70f, 0x4ad2, {0x8a, 0x5f, 0x35, 0xdf, 0x33, 0x43, 0xf5, 0x1e} } + +typedef +EFI_DEVICE_PATH_PROTOCOL* +(EFIAPI *EFI_DEVICE_PATH_FROM_TEXT_NODE) ( + IN CONST CHAR16 *TextDeviceNode + ); + +typedef +EFI_DEVICE_PATH_PROTOCOL* +(EFIAPI *EFI_DEVICE_PATH_FROM_TEXT_PATH) ( + IN CONST CHAR16 *TextDevicePath + ); + +typedef struct { + EFI_DEVICE_PATH_FROM_TEXT_NODE ConvertTextToDeviceNode; + EFI_DEVICE_PATH_FROM_TEXT_PATH ConvertTextToDevicePath; +} EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL; + +#endif diff --git a/gnu-efi/inc/efierr.h b/gnu-efi/inc/efierr.h new file mode 100644 index 0000000..5a66e1a --- /dev/null +++ b/gnu-efi/inc/efierr.h @@ -0,0 +1,68 @@ +#ifndef _EFI_ERR_H +#define _EFI_ERR_H + +/*++ + +Copyright (c) 1998 Intel Corporation + +Module Name: + + efierr.h + +Abstract: + + EFI error codes + + + + +Revision History + +--*/ + + +#define EFIWARN(a) (a) +#define EFI_ERROR(a) (((INTN) a) < 0) + + +#define EFI_SUCCESS 0 +#define EFI_LOAD_ERROR EFIERR(1) +#define EFI_INVALID_PARAMETER EFIERR(2) +#define EFI_UNSUPPORTED EFIERR(3) +#define EFI_BAD_BUFFER_SIZE EFIERR(4) +#define EFI_BUFFER_TOO_SMALL EFIERR(5) +#define EFI_NOT_READY EFIERR(6) +#define EFI_DEVICE_ERROR EFIERR(7) +#define EFI_WRITE_PROTECTED EFIERR(8) +#define EFI_OUT_OF_RESOURCES EFIERR(9) +#define EFI_VOLUME_CORRUPTED EFIERR(10) +#define EFI_VOLUME_FULL EFIERR(11) +#define EFI_NO_MEDIA EFIERR(12) +#define EFI_MEDIA_CHANGED EFIERR(13) +#define EFI_NOT_FOUND EFIERR(14) +#define EFI_ACCESS_DENIED EFIERR(15) +#define EFI_NO_RESPONSE EFIERR(16) +#define EFI_NO_MAPPING EFIERR(17) +#define EFI_TIMEOUT EFIERR(18) +#define EFI_NOT_STARTED EFIERR(19) +#define EFI_ALREADY_STARTED EFIERR(20) +#define EFI_ABORTED EFIERR(21) +#define EFI_ICMP_ERROR EFIERR(22) +#define EFI_TFTP_ERROR EFIERR(23) +#define EFI_PROTOCOL_ERROR EFIERR(24) +#define EFI_INCOMPATIBLE_VERSION EFIERR(25) +#define EFI_SECURITY_VIOLATION EFIERR(26) +#define EFI_CRC_ERROR EFIERR(27) +#define EFI_END_OF_MEDIA EFIERR(28) +#define EFI_END_OF_FILE EFIERR(31) +#define EFI_INVALID_LANGUAGE EFIERR(32) +#define EFI_COMPROMISED_DATA EFIERR(33) + +#define EFI_WARN_UNKOWN_GLYPH EFIWARN(1) +#define EFI_WARN_UNKNOWN_GLYPH EFIWARN(1) +#define EFI_WARN_DELETE_FAILURE EFIWARN(2) +#define EFI_WARN_WRITE_FAILURE EFIWARN(3) +#define EFI_WARN_BUFFER_TOO_SMALL EFIWARN(4) + +#endif + diff --git a/gnu-efi/inc/efifs.h b/gnu-efi/inc/efifs.h new file mode 100644 index 0000000..fc595d1 --- /dev/null +++ b/gnu-efi/inc/efifs.h @@ -0,0 +1,116 @@ +#ifndef _EFI_FS_H +#define _EFI_FS_H + +/*++ + +Copyright (c) 1998 Intel Corporation + +Module Name: + + efifs.h + +Abstract: + + EFI File System structures + + + +Revision History + +--*/ + + +// +// EFI Partition header (normaly starts in LBA 1) +// + +#define EFI_PARTITION_SIGNATURE 0x5053595320494249 +#define EFI_PARTITION_REVISION 0x00010001 +#define MIN_EFI_PARTITION_BLOCK_SIZE 512 +#define EFI_PARTITION_LBA 1 + +typedef struct _EFI_PARTITION_HEADER { + EFI_TABLE_HEADER Hdr; + UINT32 DirectoryAllocationNumber; + UINT32 BlockSize; + EFI_LBA FirstUsableLba; + EFI_LBA LastUsableLba; + EFI_LBA UnusableSpace; + EFI_LBA FreeSpace; + EFI_LBA RootFile; + EFI_LBA SecutiryFile; +} EFI_PARTITION_HEADER; + + +// +// File header +// + +#define EFI_FILE_HEADER_SIGNATURE 0x454c494620494249 +#define EFI_FILE_HEADER_REVISION 0x00010000 +#define EFI_FILE_STRING_SIZE 260 + +typedef struct _EFI_FILE_HEADER { + EFI_TABLE_HEADER Hdr; + UINT32 Class; + UINT32 LBALOffset; + EFI_LBA Parent; + UINT64 FileSize; + UINT64 FileAttributes; + EFI_TIME FileCreateTime; + EFI_TIME FileModificationTime; + EFI_GUID VendorGuid; + CHAR16 FileString[EFI_FILE_STRING_SIZE]; +} EFI_FILE_HEADER; + + +// +// Return the file's first LBAL which is in the same +// logical block as the file header +// + +#define EFI_FILE_LBAL(a) ((EFI_LBAL *) (((CHAR8 *) (a)) + (a)->LBALOffset)) + +#define EFI_FILE_CLASS_FREE_SPACE 1 +#define EFI_FILE_CLASS_EMPTY 2 +#define EFI_FILE_CLASS_NORMAL 3 + + +// +// Logical Block Address List - the fundemental block +// description structure +// + +#define EFI_LBAL_SIGNATURE 0x4c41424c20494249 +#define EFI_LBAL_REVISION 0x00010000 + +typedef struct _EFI_LBAL { + EFI_TABLE_HEADER Hdr; + UINT32 Class; + EFI_LBA Parent; + EFI_LBA Next; + UINT32 ArraySize; + UINT32 ArrayCount; +} EFI_LBAL; + +// Array size +#define EFI_LBAL_ARRAY_SIZE(lbal,offs,blks) \ + (((blks) - (offs) - (lbal)->Hdr.HeaderSize) / sizeof(EFI_RL)) + +// +// Logical Block run-length +// + +typedef struct { + EFI_LBA Start; + UINT64 Length; +} EFI_RL; + +// +// Return the run-length structure from an LBAL header +// + +#define EFI_LBAL_RL(a) ((EFI_RL*) (((CHAR8 *) (a)) + (a)->Hdr.HeaderSize)) + +#endif + diff --git a/gnu-efi/inc/efigpt.h b/gnu-efi/inc/efigpt.h new file mode 100644 index 0000000..d1694ae --- /dev/null +++ b/gnu-efi/inc/efigpt.h @@ -0,0 +1,68 @@ +#ifndef _EFI_GPT_H +#define _EFI_GPT_H +/*++ + +Copyright (c) 1998 Intel Corporation + +Module Name: + + EfiGpt.h + +Abstract: + Include file for EFI partitioning scheme + + + +Revision History + +--*/ + +#define PRIMARY_PART_HEADER_LBA 1 + +typedef struct { + EFI_TABLE_HEADER Header; + EFI_LBA MyLBA; + EFI_LBA AlternateLBA; + EFI_LBA FirstUsableLBA; + EFI_LBA LastUsableLBA; + EFI_GUID DiskGUID; + EFI_LBA PartitionEntryLBA; + UINT32 NumberOfPartitionEntries; + UINT32 SizeOfPartitionEntry; + UINT32 PartitionEntryArrayCRC32; +} EFI_PARTITION_TABLE_HEADER; + +#define EFI_PTAB_HEADER_ID "EFI PART" + +typedef struct { + EFI_GUID PartitionTypeGUID; + EFI_GUID UniquePartitionGUID; + EFI_LBA StartingLBA; + EFI_LBA EndingLBA; + UINT64 Attributes; + CHAR16 PartitionName[36]; +} EFI_PARTITION_ENTRY; + +// +// EFI Partition Attributes +// +#define EFI_PART_USED_BY_EFI 0x0000000000000001 +#define EFI_PART_REQUIRED_TO_FUNCTION 0x0000000000000002 +#define EFI_PART_USED_BY_OS 0x0000000000000004 +#define EFI_PART_REQUIRED_BY_OS 0x0000000000000008 +#define EFI_PART_BACKUP_REQUIRED 0x0000000000000010 +#define EFI_PART_USER_DATA 0x0000000000000020 +#define EFI_PART_CRITICAL_USER_DATA 0x0000000000000040 +#define EFI_PART_REDUNDANT_PARTITION 0x0000000000000080 + +#define EFI_PART_TYPE_UNUSED_GUID \ + { 0x00000000, 0x0000, 0x0000, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} } + +#define EFI_PART_TYPE_EFI_SYSTEM_PART_GUID \ + { 0xc12a7328, 0xf81f, 0x11d2, {0xba, 0x4b, 0x00, 0xa0, 0xc9, 0x3e, 0xc9, 0x3b} } + +#define EFI_PART_TYPE_LEGACY_MBR_GUID \ + { 0x024dee41, 0x33e7, 0x11d3, {0x9d, 0x69, 0x00, 0x08, 0xc7, 0x81, 0xf3, 0x9f} } + +#endif + diff --git a/gnu-efi/inc/efiip.h b/gnu-efi/inc/efiip.h new file mode 100644 index 0000000..8395079 --- /dev/null +++ b/gnu-efi/inc/efiip.h @@ -0,0 +1,459 @@ +#ifndef _EFI_IP_H +#define _EFI_IP_H + +/*++ +Copyright (c) 2013 Intel Corporation + +--*/ + +#define EFI_IP4_SERVICE_BINDING_PROTOCOL \ + {0xc51711e7,0xb4bf,0x404a,{0xbf,0xb8,0x0a,0x04, 0x8e,0xf1,0xff,0xe4}} + +#define EFI_IP4_PROTOCOL \ + {0x41d94cd2,0x35b6,0x455a,{0x82,0x58,0xd4,0xe5,0x13,0x34,0xaa,0xdd}} + +#define EFI_IP6_SERVICE_BINDING_PROTOCOL \ + {0xec835dd3,0xfe0f,0x617b,{0xa6,0x21,0xb3,0x50,0xc3,0xe1,0x33,0x88}} + +#define EFI_IP6_PROTOCOL \ + {0x2c8759d5,0x5c2d,0x66ef,{0x92,0x5f,0xb6,0x6c,0x10,0x19,0x57,0xe2}} + +INTERFACE_DECL(_EFI_IP4); +INTERFACE_DECL(_EFI_IP6); + +typedef struct { + EFI_HANDLE InstanceHandle; + EFI_IPv4_ADDRESS Ip4Address; + EFI_IPv4_ADDRESS SubnetMask; +} EFI_IP4_ADDRESS_PAIR; + +typedef struct { + EFI_HANDLE DriverHandle; + UINT32 AddressCount; + EFI_IP4_ADDRESS_PAIR AddressPairs[1]; +} EFI_IP4_VARIABLE_DATA; + +typedef struct { + UINT8 DefaultProtocol; + BOOLEAN AcceptAnyProtocol; + BOOLEAN AcceptIcmpErrors; + BOOLEAN AcceptBroadcast; + BOOLEAN AcceptPromiscuous; + BOOLEAN UseDefaultAddress; + EFI_IPv4_ADDRESS StationAddress; + EFI_IPv4_ADDRESS SubnetMask; + UINT8 TypeOfService; + UINT8 TimeToLive; + BOOLEAN DoNotFragment; + BOOLEAN RawData; + UINT32 ReceiveTimeout; + UINT32 TransmitTimeout; +} EFI_IP4_CONFIG_DATA; + +typedef struct { + EFI_IPv4_ADDRESS SubnetAddress; + EFI_IPv4_ADDRESS SubnetMask; + EFI_IPv4_ADDRESS GatewayAddress; +} EFI_IP4_ROUTE_TABLE; + +typedef struct { + UINT8 Type; + UINT8 Code; +} EFI_IP4_ICMP_TYPE; + +typedef struct { + BOOLEAN IsStarted; + UINT32 MaxPacketSize; + EFI_IP4_CONFIG_DATA ConfigData; + BOOLEAN IsConfigured; + UINT32 GroupCount; + EFI_IPv4_ADDRESS *GroupTable; + UINT32 RouteCount; + EFI_IP4_ROUTE_TABLE *RouteTable; + UINT32 IcmpTypeCount; + EFI_IP4_ICMP_TYPE *IcmpTypeList; +} EFI_IP4_MODE_DATA; + +typedef +EFI_STATUS +(EFIAPI *EFI_IP4_GET_MODE_DATA) ( + IN struct _EFI_IP4 *This, + OUT EFI_IP4_MODE_DATA *Ip4ModeData OPTIONAL, + OUT EFI_MANAGED_NETWORK_CONFIG_DATA *MnpConfigData OPTIONAL, + OUT EFI_SIMPLE_NETWORK_MODE *SnpModeData OPTIONAL + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_IP4_CONFIGURE) ( + IN struct _EFI_IP4 *This, + IN EFI_IP4_CONFIG_DATA *IpConfigData OPTIONAL + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_IP4_GROUPS) ( + IN struct _EFI_IP4 *This, + IN BOOLEAN JoinFlag, + IN EFI_IPv4_ADDRESS *GroupAddress OPTIONAL + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_IP4_ROUTES) ( + IN struct _EFI_IP4 *This, + IN BOOLEAN DeleteRoute, + IN EFI_IPv4_ADDRESS *SubnetAddress, + IN EFI_IPv4_ADDRESS *SubnetMask, + IN EFI_IPv4_ADDRESS *GatewayAddress + ); + +#pragma pack(1) +typedef struct { + UINT8 HeaderLength:4; + UINT8 Version:4; + UINT8 TypeOfService; + UINT16 TotalLength; + UINT16 Identification; + UINT16 Fragmentation; + UINT8 TimeToLive; + UINT8 Protocol; + UINT16 Checksum; + EFI_IPv4_ADDRESS SourceAddress; + EFI_IPv4_ADDRESS DestinationAddress; +} EFI_IP4_HEADER; +#pragma pack() + +typedef struct { + UINT32 FragmentLength; + VOID *FragmentBuffer; +} EFI_IP4_FRAGMENT_DATA; + +typedef struct { + EFI_TIME TimeStamp; + EFI_EVENT RecycleSignal; + UINT32 HeaderLength; + EFI_IP4_HEADER *Header; + UINT32 OptionsLength; + VOID *Options; + UINT32 DataLength; + UINT32 FragmentCount; + EFI_IP4_FRAGMENT_DATA FragmentTable[1]; +} EFI_IP4_RECEIVE_DATA; + +typedef struct { + EFI_IPv4_ADDRESS SourceAddress; + EFI_IPv4_ADDRESS GatewayAddress; + UINT8 Protocol; + UINT8 TypeOfService; + UINT8 TimeToLive; + BOOLEAN DoNotFragment; +} EFI_IP4_OVERRIDE_DATA; + +typedef struct { + EFI_IPv4_ADDRESS DestinationAddress; + EFI_IP4_OVERRIDE_DATA *OverrideData; + UINT32 OptionsLength; + VOID *OptionsBuffer; + UINT32 TotalDataLength; + UINT32 FragmentCount; + EFI_IP4_FRAGMENT_DATA FragmentTable[1]; +} EFI_IP4_TRANSMIT_DATA; + +typedef struct { + EFI_EVENT Event; + EFI_STATUS Status; + union { + EFI_IP4_RECEIVE_DATA *RxData; + EFI_IP4_TRANSMIT_DATA *TxData; + } Packet; +} EFI_IP4_COMPLETION_TOKEN; + +typedef +EFI_STATUS +(EFIAPI *EFI_IP4_TRANSMIT) ( + IN struct _EFI_IP4 *This, + IN EFI_IP4_COMPLETION_TOKEN *Token + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_IP4_RECEIVE) ( + IN struct _EFI_IP4 *This, + IN EFI_IP4_COMPLETION_TOKEN *Token + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_IP4_CANCEL)( + IN struct _EFI_IP4 *This, + IN EFI_IP4_COMPLETION_TOKEN *Token OPTIONAL + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_IP4_POLL) ( + IN struct _EFI_IP4 *This + ); + +typedef struct _EFI_IP4 { + EFI_IP4_GET_MODE_DATA GetModeData; + EFI_IP4_CONFIGURE Configure; + EFI_IP4_GROUPS Groups; + EFI_IP4_ROUTES Routes; + EFI_IP4_TRANSMIT Transmit; + EFI_IP4_RECEIVE Receive; + EFI_IP4_CANCEL Cancel; + EFI_IP4_POLL Poll; +} EFI_IP4; + +typedef struct { + UINT8 DefaultProtocol; + BOOLEAN AcceptAnyProtocol; + BOOLEAN AcceptIcmpErrors; + BOOLEAN AcceptPromiscuous; + EFI_IPv6_ADDRESS DestinationAddress; + EFI_IPv6_ADDRESS StationAddress; + UINT8 TrafficClass; + UINT8 HopLimit; + UINT32 FlowLabel; + UINT32 ReceiveTimeout; + UINT32 TransmitTimeout; +} EFI_IP6_CONFIG_DATA; + +typedef struct { + EFI_IPv6_ADDRESS Address; + UINT8 PrefixLength; +} EFI_IP6_ADDRESS_INFO; + +typedef struct { + EFI_IPv6_ADDRESS Gateway; + EFI_IPv6_ADDRESS Destination; + UINT8 PrefixLength; +} EFI_IP6_ROUTE_TABLE; + +typedef enum { + EfiNeighborInComplete, + EfiNeighborReachable, + EfiNeighborStale, + EfiNeighborDelay, + EfiNeighborProbe +} EFI_IP6_NEIGHBOR_STATE; + +typedef struct { + EFI_IPv6_ADDRESS Neighbor; + EFI_MAC_ADDRESS LinkAddress; + EFI_IP6_NEIGHBOR_STATE State; +} EFI_IP6_NEIGHBOR_CACHE; + +typedef struct { + UINT8 Type; + UINT8 Code; +} EFI_IP6_ICMP_TYPE; + +//*********************************************************** +// ICMPv6 type definitions for error messages +//*********************************************************** +#define ICMP_V6_DEST_UNREACHABLE 0x1 +#define ICMP_V6_PACKET_TOO_BIG 0x2 +#define ICMP_V6_TIME_EXCEEDED 0x3 +#define ICMP_V6_PARAMETER_PROBLEM 0x4 + +//*********************************************************** +// ICMPv6 type definition for informational messages +//*********************************************************** +#define ICMP_V6_ECHO_REQUEST 0x80 +#define ICMP_V6_ECHO_REPLY 0x81 +#define ICMP_V6_LISTENER_QUERY 0x82 +#define ICMP_V6_LISTENER_REPORT 0x83 +#define ICMP_V6_LISTENER_DONE 0x84 +#define ICMP_V6_ROUTER_SOLICIT 0x85 +#define ICMP_V6_ROUTER_ADVERTISE 0x86 +#define ICMP_V6_NEIGHBOR_SOLICIT 0x87 +#define ICMP_V6_NEIGHBOR_ADVERTISE 0x88 +#define ICMP_V6_REDIRECT 0x89 +#define ICMP_V6_LISTENER_REPORT_2 0x8F + +//*********************************************************** +// ICMPv6 code definitions for ICMP_V6_DEST_UNREACHABLE +//*********************************************************** +#define ICMP_V6_NO_ROUTE_TO_DEST 0x0 +#define ICMP_V6_COMM_PROHIBITED 0x1 +#define ICMP_V6_BEYOND_SCOPE 0x2 +#define ICMP_V6_ADDR_UNREACHABLE 0x3 +#define ICMP_V6_PORT_UNREACHABLE 0x4 +#define ICMP_V6_SOURCE_ADDR_FAILED 0x5 +#define ICMP_V6_ROUTE_REJECTED 0x6 + +//*********************************************************** +// ICMPv6 code definitions for ICMP_V6_TIME_EXCEEDED +//*********************************************************** +#define ICMP_V6_TIMEOUT_HOP_LIMIT 0x0 +#define ICMP_V6_TIMEOUT_REASSEMBLE 0x1 + +//*********************************************************** +// ICMPv6 code definitions for ICMP_V6_PARAMETER_PROBLEM +//*********************************************************** +#define ICMP_V6_ERRONEOUS_HEADER 0x0 +#define ICMP_V6_UNRECOGNIZE_NEXT_HDR 0x1 +#define ICMP_V6_UNRECOGNIZE_OPTION 0x2 + +typedef struct { + BOOLEAN IsStarted; + UINT32 MaxPacketSize; + EFI_IP6_CONFIG_DATA ConfigData; + BOOLEAN IsConfigured; + UINT32 AddressCount; + EFI_IP6_ADDRESS_INFO *AddressList; + UINT32 GroupCount; + EFI_IPv6_ADDRESS *GroupTable; + UINT32 RouteCount; + EFI_IP6_ROUTE_TABLE *RouteTable; + UINT32 NeighborCount; + EFI_IP6_NEIGHBOR_CACHE *NeighborCache; + UINT32 PrefixCount; + EFI_IP6_ADDRESS_INFO *PrefixTable; + UINT32 IcmpTypeCount; + EFI_IP6_ICMP_TYPE *IcmpTypeList; +} EFI_IP6_MODE_DATA; + +typedef +EFI_STATUS +(EFIAPI *EFI_IP6_GET_MODE_DATA) ( + IN struct _EFI_IP6 *This, + OUT EFI_IP6_MODE_DATA *Ip6ModeData OPTIONAL, + OUT EFI_MANAGED_NETWORK_CONFIG_DATA *MnpConfigData OPTIONAL, + OUT EFI_SIMPLE_NETWORK_MODE *SnpModeData OPTIONAL + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_IP6_CONFIGURE) ( + IN struct _EFI_IP6 *This, + IN EFI_IP6_CONFIG_DATA *Ip6ConfigData OPTIONAL + ); +typedef +EFI_STATUS +(EFIAPI *EFI_IP6_GROUPS) ( + IN struct _EFI_IP6 *This, + IN BOOLEAN JoinFlag, + IN EFI_IPv6_ADDRESS *GroupAddress OPTIONAL + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_IP6_ROUTES) ( + IN struct _EFI_IP6 *This, + IN BOOLEAN DeleteRoute, + IN EFI_IPv6_ADDRESS *Destination OPTIONAL, + IN UINT8 PrefixLength, + IN EFI_IPv6_ADDRESS *GatewayAddress OPTIONAL + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_IP6_NEIGHBORS) ( + IN struct _EFI_IP6 *This, + IN BOOLEAN DeleteFlag, + IN EFI_IPv6_ADDRESS *TargetIp6Address, + IN EFI_MAC_ADDRESS *TargetLinkAddress OPTIONAL, + IN UINT32 Timeout, + IN BOOLEAN Override + ); + +typedef struct _EFI_IP6_FRAGMENT_DATA { + UINT32 FragmentLength; + VOID *FragmentBuffer; +} EFI_IP6_FRAGMENT_DATA; + +typedef struct _EFI_IP6_OVERRIDE_DATA { + UINT8 Protocol; + UINT8 HopLimit; + UINT32 FlowLabel; +} EFI_IP6_OVERRIDE_DATA; + +typedef struct _EFI_IP6_TRANSMIT_DATA { + EFI_IPv6_ADDRESS DestinationAddress; + EFI_IP6_OVERRIDE_DATA *OverrideData; + UINT32 ExtHdrsLength; + VOID *ExtHdrs; + UINT8 NextHeader; + UINT32 DataLength; + UINT32 FragmentCount; + EFI_IP6_FRAGMENT_DATA FragmentTable[1]; +} EFI_IP6_TRANSMIT_DATA; + +#pragma pack(1) +typedef struct _EFI_IP6_HEADER { + UINT8 TrafficClassH:4; + UINT8 Version:4; + UINT8 FlowLabelH:4; + UINT8 TrafficClassL:4; + UINT16 FlowLabelL; + UINT16 PayloadLength; + UINT8 NextHeader; + UINT8 HopLimit; + EFI_IPv6_ADDRESS SourceAddress; + EFI_IPv6_ADDRESS DestinationAddress; +} EFI_IP6_HEADER; +#pragma pack() + +typedef struct _EFI_IP6_RECEIVE_DATA { + EFI_TIME TimeStamp; + EFI_EVENT RecycleSignal; + UINT32 HeaderLength; + EFI_IP6_HEADER *Header; + UINT32 DataLength; + UINT32 FragmentCount; + EFI_IP6_FRAGMENT_DATA FragmentTable[1]; +} EFI_IP6_RECEIVE_DATA; + +typedef struct { + EFI_EVENT Event; + EFI_STATUS Status; + union { + EFI_IP6_RECEIVE_DATA *RxData; + EFI_IP6_TRANSMIT_DATA *TxData; + } Packet; +} EFI_IP6_COMPLETION_TOKEN; + +typedef +EFI_STATUS +(EFIAPI *EFI_IP6_TRANSMIT) ( + IN struct _EFI_IP6 *This, + IN EFI_IP6_COMPLETION_TOKEN *Token + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_IP6_RECEIVE) ( + IN struct _EFI_IP6 *This, + IN EFI_IP6_COMPLETION_TOKEN *Token + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_IP6_CANCEL)( + IN struct _EFI_IP6 *This, + IN EFI_IP6_COMPLETION_TOKEN *Token OPTIONAL + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_IP6_POLL) ( + IN struct _EFI_IP6 *This + ); + +typedef struct _EFI_IP6 { + EFI_IP6_GET_MODE_DATA GetModeData; + EFI_IP6_CONFIGURE Configure; + EFI_IP6_GROUPS Groups; + EFI_IP6_ROUTES Routes; + EFI_IP6_NEIGHBORS Neighbors; + EFI_IP6_TRANSMIT Transmit; + EFI_IP6_RECEIVE Receive; + EFI_IP6_CANCEL Cancel; + EFI_IP6_POLL Poll; +} EFI_IP6; + +#endif /* _EFI_IP_H */ diff --git a/gnu-efi/inc/efilib.h b/gnu-efi/inc/efilib.h new file mode 100644 index 0000000..62c577d --- /dev/null +++ b/gnu-efi/inc/efilib.h @@ -0,0 +1,1037 @@ +#ifndef _EFILIB_INCLUDE_ +#define _EFILIB_INCLUDE_ + +/*++ + +Copyright (c) 2000 Intel Corporation + +Module Name: + + efilib.h + +Abstract: + + EFI library functions + + + +Revision History + +--*/ + +#include "efidebug.h" +#include "efipart.h" +#include "efilibplat.h" +#include "efilink.h" +#include "efirtlib.h" +#include "efistdarg.h" +#include "pci22.h" +#include "libsmbios.h" + +// +// Public read-only data in the EFI library +// + +extern EFI_SYSTEM_TABLE *ST; +#define gST ST +extern EFI_BOOT_SERVICES *BS; +#define gBS BS +extern EFI_RUNTIME_SERVICES *RT; +#define gRT RT + +extern EFI_GUID gEfiDevicePathProtocolGuid; +#define DevicePathProtocol gEfiDevicePathProtocolGuid +extern EFI_GUID gEfiDevicePathToTextProtocolGuid; +#define DevicePathToTextProtocol gEfiDevicePathToTextProtocolGuid +extern EFI_GUID gEfiDevicePathFromTextProtocolGuid; +#define DevicePathFromTextProtocol gEfiDevicePathFromTextProtocolGuid +extern EFI_GUID gEfiLoadedImageProtocolGuid; +#define LoadedImageProtocol gEfiLoadedImageProtocolGuid +extern EFI_GUID gEfiSimpleTextInProtocolGuid; +#define TextInProtocol gEfiSimpleTextInProtocolGuid +extern EFI_GUID gEfiSimpleTextOutProtocolGuid; +#define TextOutProtocol gEfiSimpleTextOutProtocolGuid +extern EFI_GUID gEfiGraphicsOutputProtocolGuid; +#define GraphicsOutputProtocol gEfiGraphicsOutputProtocolGuid +extern EFI_GUID gEfiEdidDiscoveredProtocolGuid; +#define EdidDiscoveredProtocol gEfiEdidDiscoveredProtocolGuid +extern EFI_GUID gEfiEdidActiveProtocolGuid; +#define EdidActiveProtocol gEfiEdidActiveProtocolGuid +extern EFI_GUID gEfiEdidOverrideProtocolGuid; +#define EdidOverrideProtocol gEfiEdidOverrideProtocolGuid +extern EFI_GUID gEfiBlockIoProtocolGuid; +#define BlockIoProtocol gEfiBlockIoProtocolGuid +extern EFI_GUID gEfiBlockIo2ProtocolGuid; +#define BlockIo2Protocol gEfiBlockIo2ProtocolGuid +extern EFI_GUID gEfiDiskIoProtocolGuid; +#define DiskIoProtocol gEfiDiskIoProtocolGuid +extern EFI_GUID gEfiDiskIo2ProtocolGuid; +#define DiskIo2Protocol gEfiDiskIo2ProtocolGuid +extern EFI_GUID gEfiSimpleFileSystemProtocolGuid; +#define FileSystemProtocol gEfiSimpleFileSystemProtocolGuid +extern EFI_GUID gEfiLoadFileProtocolGuid; +#define LoadFileProtocol gEfiLoadFileProtocolGuid +extern EFI_GUID gEfiDeviceIoProtocolGuid; +#define DeviceIoProtocol gEfiDeviceIoProtocolGuid +extern EFI_GUID VariableStoreProtocol; +extern EFI_GUID LegacyBootProtocol; +extern EFI_GUID gEfiUnicodeCollationProtocolGuid; +#define UnicodeCollationProtocol gEfiUnicodeCollationProtocolGuid +extern EFI_GUID gEfiSerialIoProtocolGuid; +#define SerialIoProtocol gEfiSerialIoProtocolGuid +extern EFI_GUID VgaClassProtocol; +extern EFI_GUID TextOutSpliterProtocol; +extern EFI_GUID ErrorOutSpliterProtocol; +extern EFI_GUID TextInSpliterProtocol; +extern EFI_GUID gEfiSimpleNetworkProtocolGuid; +#define SimpleNetworkProtocol gEfiSimpleNetworkProtocolGuid +extern EFI_GUID gEfiPxeBaseCodeProtocolGuid; +#define PxeBaseCodeProtocol gEfiPxeBaseCodeProtocolGuid +extern EFI_GUID gEfiPxeBaseCodeCallbackProtocolGuid; +#define PxeCallbackProtocol gEfiPxeBaseCodeCallbackProtocolGuid +extern EFI_GUID gEfiNetworkInterfaceIdentifierProtocolGuid; +#define NetworkInterfaceIdentifierProtocol gEfiNetworkInterfaceIdentifierProtocolGuid +extern EFI_GUID gEFiUiInterfaceProtocolGuid; +#define UiProtocol gEFiUiInterfaceProtocolGuid +extern EFI_GUID InternalShellProtocol; +extern EFI_GUID gEfiPciIoProtocolGuid; +#define PciIoProtocol gEfiPciIoProtocolGuid +extern EFI_GUID gEfiPciRootBridgeIoProtocolGuid; +extern EFI_GUID gEfiDriverBindingProtocolGuid; +#define DriverBindingProtocol gEfiDriverBindingProtocolGuid +extern EFI_GUID gEfiComponentNameProtocolGuid; +#define ComponentNameProtocol gEfiComponentNameProtocolGuid +extern EFI_GUID gEfiComponentName2ProtocolGuid; +#define ComponentName2Protocol gEfiComponentName2ProtocolGuid +extern EFI_GUID gEfiHashProtocolGuid; +#define HashProtocol gEfiHashProtocolGuid +extern EFI_GUID gEfiPlatformDriverOverrideProtocolGuid; +#define PlatformDriverOverrideProtocol gEfiPlatformDriverOverrideProtocolGuid +extern EFI_GUID gEfiBusSpecificDriverOverrideProtocolGuid; +#define BusSpecificDriverOverrideProtocol gEfiBusSpecificDriverOverrideProtocolGuid +extern EFI_GUID gEfiDriverFamilyOverrideProtocolGuid; +#define DriverFamilyOverrideProtocol gEfiDriverFamilyOverrideProtocolGuid +extern EFI_GUID gEfiEbcProtocolGuid; + +extern EFI_GUID gEfiGlobalVariableGuid; +#define EfiGlobalVariable gEfiGlobalVariableGuid +extern EFI_GUID gEfiFileInfoGuid; +#define GenericFileInfo gEfiFileInfoGuid +extern EFI_GUID gEfiFileSystemInfoGuid; +#define FileSystemInfo gEfiFileSystemInfoGuid +extern EFI_GUID gEfiFileSystemVolumeLabelInfoIdGuid; +#define FileSystemVolumeLabelInfo gEfiFileSystemVolumeLabelInfoIdGuid +extern EFI_GUID gEfiPcAnsiGuid; +#define PcAnsiProtocol gEfiPcAnsiGuid +extern EFI_GUID gEfiVT100Guid; +#define Vt100Protocol gEfiVT100Guid +extern EFI_GUID gEfiVT100PlusGuid; +extern EFI_GUID gEfiVTUTF8Guid; + +extern EFI_GUID NullGuid; +extern EFI_GUID UnknownDevice; + +extern EFI_GUID EfiPartTypeSystemPartitionGuid; +extern EFI_GUID EfiPartTypeLegacyMbrGuid; + +extern EFI_GUID MpsTableGuid; +extern EFI_GUID AcpiTableGuid; +extern EFI_GUID SMBIOSTableGuid; +extern EFI_GUID SMBIOS3TableGuid; +extern EFI_GUID SalSystemTableGuid; + +extern EFI_GUID SimplePointerProtocol; +extern EFI_GUID AbsolutePointerProtocol; + +extern EFI_GUID gEfiDebugImageInfoTableGuid; +extern EFI_GUID gEfiDebugSupportProtocolGuid; + +// +// EFI Variable strings +// +#define LOAD_OPTION_ACTIVE 0x00000001 + +#define VarLanguageCodes L"LangCodes" +#define VarLanguage L"Lang" +#define VarTimeout L"Timeout" +#define VarConsoleInp L"ConIn" +#define VarConsoleOut L"ConOut" +#define VarErrorOut L"ErrOut" +#define VarBootOption L"Boot%04x" +#define VarBootOrder L"BootOrder" +#define VarBootNext L"BootNext" +#define VarBootCurrent L"BootCurrent" +#define VarDriverOption L"Driver%04x" +#define VarDriverOrder L"DriverOrder" +#define VarConsoleInpDev L"ConInDev" +#define VarConsoleOutDev L"ConOutDev" +#define VarErrorOutDev L"ErrOutDev" + +#define LanguageCodeEnglish "eng" + +extern EFI_DEVICE_PATH RootDevicePath[]; +extern EFI_DEVICE_PATH EndDevicePath[]; +extern EFI_DEVICE_PATH EndInstanceDevicePath[]; + +// +// Other public data in the EFI library +// + +extern EFI_MEMORY_TYPE PoolAllocationType; + +// +// STATIC - Name is internal to the module +// INTERNAL - Name is internal to the component (i.e., directory) +// BOOTSERVCE - Name of a boot service function +// + +#define STATIC +#define INTERNAL +#define BOOTSERVICE + +// +// Prototypes +// + +VOID +InitializeLib ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + +VOID +InitializeUnicodeSupport ( + CHAR8 *LangCode + ); + +VOID +EFIDebugVariable ( + VOID + ); + +VOID +Exit( + IN EFI_STATUS ExitStatus, + IN UINTN ExitDataSize, + IN CHAR16 *ExitData OPTIONAL + ); + +INTN +GetShellArgcArgv( + EFI_HANDLE ImageHandle, + CHAR16 **Argv[] /* Statically allocated */ + ); + +VOID +SetCrc ( + IN OUT EFI_TABLE_HEADER *Hdr + ); + +VOID +SetCrcAltSize ( + IN UINTN Size, + IN OUT EFI_TABLE_HEADER *Hdr + ); + +BOOLEAN +CheckCrc ( + IN UINTN MaxSize, + IN OUT EFI_TABLE_HEADER *Hdr + ); + +BOOLEAN +CheckCrcAltSize ( + IN UINTN MaxSize, + IN UINTN Size, + IN OUT EFI_TABLE_HEADER *Hdr + ); + +UINT32 +CalculateCrc ( + UINT8 *pt, + UINTN Size + ); + +VOID +ZeroMem ( + IN VOID *Buffer, + IN UINTN Size + ); + +VOID +SetMem ( + IN VOID *Buffer, + IN UINTN Size, + IN UINT8 Value + ); + +VOID +CopyMem ( + IN VOID *Dest, + IN CONST VOID *Src, + IN UINTN len + ); + +INTN +CompareMem ( + IN CONST VOID *Dest, + IN CONST VOID *Src, + IN UINTN len + ); + +INTN +StrCmp ( + IN CONST CHAR16 *s1, + IN CONST CHAR16 *s2 + ); + +INTN +StrnCmp ( + IN CONST CHAR16 *s1, + IN CONST CHAR16 *s2, + IN UINTN len + ); + +INTN +StriCmp ( + IN CONST CHAR16 *s1, + IN CONST CHAR16 *s2 + ); + +VOID +StrLwr ( + IN CHAR16 *Str + ); + +VOID +StrUpr ( + IN CHAR16 *Str + ); + +VOID +StrCpy ( + IN CHAR16 *Dest, + IN CONST CHAR16 *Src + ); + +VOID +StrnCpy ( + IN CHAR16 *Dest, + IN CONST CHAR16 *Src, + IN UINTN Len + ); + +CHAR16 * +StpCpy ( + IN CHAR16 *Dest, + IN CONST CHAR16 *Src + ); + +CHAR16 * +StpnCpy ( + IN CHAR16 *Dest, + IN CONST CHAR16 *Src, + IN UINTN Len + ); + +VOID +StrCat ( + IN CHAR16 *Dest, + IN CONST CHAR16 *Src + ); + +VOID +StrnCat ( + IN CHAR16 *Dest, + IN CONST CHAR16 *Src, + IN UINTN Len + ); + +UINTN +StrLen ( + IN CONST CHAR16 *s1 + ); + +UINTN +StrnLen ( + IN CONST CHAR16 *s1, + IN UINTN Len + ); + +UINTN +StrSize ( + IN CONST CHAR16 *s1 + ); + +CHAR16 * +StrDuplicate ( + IN CONST CHAR16 *Src + ); + +UINTN +strlena ( + IN CONST CHAR8 *s1 + ); + +UINTN +strcmpa ( + IN CONST CHAR8 *s1, + IN CONST CHAR8 *s2 + ); + +UINTN +strncmpa ( + IN CONST CHAR8 *s1, + IN CONST CHAR8 *s2, + IN UINTN len + ); + +UINTN +xtoi ( + CONST CHAR16 *str + ); + +UINTN +Atoi ( + CONST CHAR16 *str + ); + +BOOLEAN +MetaMatch ( + IN CHAR16 *String, + IN CHAR16 *Pattern + ); + +BOOLEAN +MetaiMatch ( + IN CHAR16 *String, + IN CHAR16 *Pattern + ); + +UINT64 +LShiftU64 ( + IN UINT64 Operand, + IN UINTN Count + ); + +UINT64 +RShiftU64 ( + IN UINT64 Operand, + IN UINTN Count + ); + +UINT64 +MultU64x32 ( + IN UINT64 Multiplicand, + IN UINTN Multiplier + ); + +UINT64 +DivU64x32 ( + IN UINT64 Dividend, + IN UINTN Divisor, + OUT UINTN *Remainder OPTIONAL + ); + +VOID +InitializeLock ( + IN OUT FLOCK *Lock, + IN EFI_TPL Priority + ); + +VOID +AcquireLock ( + IN FLOCK *Lock + ); + +VOID +ReleaseLock ( + IN FLOCK *Lock + ); + + +INTN +CompareGuid( + IN EFI_GUID *Guid1, + IN EFI_GUID *Guid2 + ); + +VOID * +AllocatePool ( + IN UINTN Size + ); + +VOID * +AllocateZeroPool ( + IN UINTN Size + ); + +VOID * +ReallocatePool ( + IN VOID *OldPool, + IN UINTN OldSize, + IN UINTN NewSize + ); + +VOID +FreePool ( + IN VOID *p + ); + + +VOID +Output ( + IN CHAR16 *Str + ); + +VOID +Input ( + IN CHAR16 *Prompt OPTIONAL, + OUT CHAR16 *InStr, + IN UINTN StrLen + ); + +VOID +IInput ( + IN SIMPLE_TEXT_OUTPUT_INTERFACE *ConOut, + IN SIMPLE_INPUT_INTERFACE *ConIn, + IN CHAR16 *Prompt OPTIONAL, + OUT CHAR16 *InStr, + IN UINTN StrLen + ); + +UINTN +Print ( + IN CONST CHAR16 *fmt, + ... + ); + +UINTN +VPrint ( + IN CONST CHAR16 *fmt, + va_list args + ); + +UINTN +SPrint ( + OUT CHAR16 *Str, + IN UINTN StrSize, + IN CONST CHAR16 *fmt, + ... + ); + +UINTN +VSPrint ( + OUT CHAR16 *Str, + IN UINTN StrSize, + IN CONST CHAR16 *fmt, + va_list args + ); + +CHAR16 * +VPoolPrint ( + IN CONST CHAR16 *fmt, + va_list args + ); + +CHAR16 * +PoolPrint ( + IN CONST CHAR16 *fmt, + ... + ); + +typedef struct { + CHAR16 *str; + UINTN len; + UINTN maxlen; +} POOL_PRINT; + +CHAR16 * +CatPrint ( + IN OUT POOL_PRINT *Str, + IN CONST CHAR16 *fmt, + ... + ); + +UINTN +PrintAt ( + IN UINTN Column, + IN UINTN Row, + IN CONST CHAR16 *fmt, + ... + ); + +UINTN +IPrint ( + IN SIMPLE_TEXT_OUTPUT_INTERFACE *Out, + IN CONST CHAR16 *fmt, + ... + ); + +UINTN +IPrintAt ( + IN SIMPLE_TEXT_OUTPUT_INTERFACE *Out, + IN UINTN Column, + IN UINTN Row, + IN CONST CHAR16 *fmt, + ... + ); + +UINTN +APrint ( + IN CONST CHAR8 *fmt, + ... + ); + +VOID +ValueToHex ( + IN CHAR16 *Buffer, + IN UINT64 v + ); + +VOID +ValueToString ( + IN CHAR16 *Buffer, + IN BOOLEAN Comma, + IN INT64 v + ); + +VOID +FloatToString ( + IN CHAR16 *Buffer, + IN BOOLEAN Comma, + IN double v + ); + +VOID +TimeToString ( + OUT CHAR16 *Buffer, + IN EFI_TIME *Time + ); + +VOID +GuidToString ( + OUT CHAR16 *Buffer, + IN EFI_GUID *Guid + ); + +VOID +StatusToString ( + OUT CHAR16 *Buffer, + EFI_STATUS Status + ); + +VOID +DumpHex ( + IN UINTN Indent, + IN UINTN Offset, + IN UINTN DataSize, + IN VOID *UserData + ); + +BOOLEAN +GrowBuffer( + IN OUT EFI_STATUS *Status, + IN OUT VOID **Buffer, + IN UINTN BufferSize + ); + +EFI_MEMORY_DESCRIPTOR * +LibMemoryMap ( + OUT UINTN *NoEntries, + OUT UINTN *MapKey, + OUT UINTN *DescriptorSize, + OUT UINT32 *DescriptorVersion + ); + +VOID * +LibGetVariable ( + IN CHAR16 *Name, + IN EFI_GUID *VendorGuid + ); + +VOID * +LibGetVariableAndSize ( + IN CHAR16 *Name, + IN EFI_GUID *VendorGuid, + OUT UINTN *VarSize + ); + +EFI_STATUS +LibDeleteVariable ( + IN CHAR16 *VarName, + IN EFI_GUID *VarGuid + ); + +EFI_STATUS +LibSetNVVariable ( + IN CHAR16 *VarName, + IN EFI_GUID *VarGuid, + IN UINTN DataSize, + IN VOID *Data + ); + +EFI_STATUS +LibSetVariable ( + IN CHAR16 *VarName, + IN EFI_GUID *VarGuid, + IN UINTN DataSize, + IN VOID *Data + ); +EFI_STATUS +LibInsertToTailOfBootOrder ( + IN UINT16 BootOption, + IN BOOLEAN OnlyInsertIfEmpty + ); + +EFI_STATUS +LibLocateProtocol ( + IN EFI_GUID *ProtocolGuid, + OUT VOID **Interface + ); + +EFI_STATUS +LibLocateHandle ( + IN EFI_LOCATE_SEARCH_TYPE SearchType, + IN EFI_GUID *Protocol OPTIONAL, + IN VOID *SearchKey OPTIONAL, + IN OUT UINTN *NoHandles, + OUT EFI_HANDLE **Buffer + ); + +EFI_STATUS +LibLocateHandleByDiskSignature ( + IN UINT8 MBRType, + IN UINT8 SignatureType, + IN VOID *Signature, + IN OUT UINTN *NoHandles, + OUT EFI_HANDLE **Buffer + ); + +EFI_STATUS +LibInstallProtocolInterfaces ( + IN OUT EFI_HANDLE *Handle, + ... + ); + +VOID +LibUninstallProtocolInterfaces ( + IN EFI_HANDLE Handle, + ... + ); + +EFI_STATUS +LibReinstallProtocolInterfaces ( + IN OUT EFI_HANDLE *Handle, + ... + ); + +EFI_EVENT +LibCreateProtocolNotifyEvent ( + IN EFI_GUID *ProtocolGuid, + IN EFI_TPL NotifyTpl, + IN EFI_EVENT_NOTIFY NotifyFunction, + IN VOID *NotifyContext, + OUT VOID *Registration + ); + +EFI_STATUS +WaitForSingleEvent ( + IN EFI_EVENT Event, + IN UINT64 Timeout OPTIONAL + ); + +VOID +WaitForEventWithTimeout ( + IN EFI_EVENT Event, + IN UINTN Timeout, + IN UINTN Row, + IN UINTN Column, + IN CHAR16 *String, + IN EFI_INPUT_KEY TimeoutKey, + OUT EFI_INPUT_KEY *Key + ); + +EFI_FILE_HANDLE +LibOpenRoot ( + IN EFI_HANDLE DeviceHandle + ); + +EFI_FILE_INFO * +LibFileInfo ( + IN EFI_FILE_HANDLE FHand + ); + +EFI_FILE_SYSTEM_INFO * +LibFileSystemInfo ( + IN EFI_FILE_HANDLE FHand + ); + +EFI_FILE_SYSTEM_VOLUME_LABEL_INFO * +LibFileSystemVolumeLabelInfo ( + IN EFI_FILE_HANDLE FHand + ); + +BOOLEAN +ValidMBR( + IN MASTER_BOOT_RECORD *Mbr, + IN EFI_BLOCK_IO *BlkIo + ); + +BOOLEAN +LibMatchDevicePaths ( + IN EFI_DEVICE_PATH *Multi, + IN EFI_DEVICE_PATH *Single + ); + +EFI_DEVICE_PATH * +LibDuplicateDevicePathInstance ( + IN EFI_DEVICE_PATH *DevPath + ); + +EFI_DEVICE_PATH * +DevicePathFromHandle ( + IN EFI_HANDLE Handle + ); + +EFI_DEVICE_PATH * +DevicePathInstance ( + IN OUT EFI_DEVICE_PATH **DevicePath, + OUT UINTN *Size + ); + +UINTN +DevicePathInstanceCount ( + IN EFI_DEVICE_PATH *DevicePath + ); + +EFI_DEVICE_PATH * +AppendDevicePath ( + IN EFI_DEVICE_PATH *Src1, + IN EFI_DEVICE_PATH *Src2 + ); + +EFI_DEVICE_PATH * +AppendDevicePathNode ( + IN EFI_DEVICE_PATH *Src1, + IN EFI_DEVICE_PATH *Src2 + ); + +EFI_DEVICE_PATH* +AppendDevicePathInstance ( + IN EFI_DEVICE_PATH *Src, + IN EFI_DEVICE_PATH *Instance + ); + +EFI_DEVICE_PATH * +FileDevicePath ( + IN EFI_HANDLE Device OPTIONAL, + IN CHAR16 *FileName + ); + +UINTN +DevicePathSize ( + IN EFI_DEVICE_PATH *DevPath + ); + +EFI_DEVICE_PATH * +DuplicateDevicePath ( + IN EFI_DEVICE_PATH *DevPath + ); + +EFI_DEVICE_PATH * +UnpackDevicePath ( + IN EFI_DEVICE_PATH *DevPath + ); + +EFI_STATUS +LibDevicePathToInterface ( + IN EFI_GUID *Protocol, + IN EFI_DEVICE_PATH *FilePath, + OUT VOID **Interface + ); + +CHAR16 * +DevicePathToStr ( + EFI_DEVICE_PATH *DevPath + ); + +// +// BugBug: I need my own include files +// +typedef struct { + UINT8 Register; + UINT8 Function; + UINT8 Device; + UINT8 Bus; + UINT32 Reserved; +} EFI_ADDRESS; + +typedef union { + UINT64 Address; + EFI_ADDRESS EfiAddress; +} EFI_PCI_ADDRESS_UNION; + + +EFI_STATUS +PciFindDeviceClass ( + IN OUT EFI_PCI_ADDRESS_UNION *Address, + IN UINT8 BaseClass, + IN UINT8 SubClass + ); + +EFI_STATUS +PciFindDevice ( + IN OUT EFI_PCI_ADDRESS_UNION *DeviceAddress, + IN UINT16 VendorId, + IN UINT16 DeviceId, + IN OUT PCI_TYPE00 *Pci + ); + +// +// SIMPLE_READ_FILE object used to access files +// + +typedef VOID *SIMPLE_READ_FILE; + +EFI_STATUS +OpenSimpleReadFile ( + IN BOOLEAN BootPolicy, + IN VOID *SourceBuffer OPTIONAL, + IN UINTN SourceSize, + IN OUT EFI_DEVICE_PATH **FilePath, + OUT EFI_HANDLE *DeviceHandle, + OUT SIMPLE_READ_FILE *SimpleReadHandle + ); + +EFI_STATUS +ReadSimpleReadFile ( + IN SIMPLE_READ_FILE SimpleReadHandle, + IN UINTN Offset, + IN OUT UINTN *ReadSize, + OUT VOID *Buffer + ); + + +VOID +CloseSimpleReadFile ( + IN SIMPLE_READ_FILE SimpleReadHandle + ); + +VOID +InitializeGuid ( + VOID + ); + +UINT8 +DecimaltoBCD( + IN UINT8 DecValue + ); + +UINT8 +BCDtoDecimal( + IN UINT8 BcdValue + ); + +EFI_STATUS +LibGetSystemConfigurationTable( + IN EFI_GUID *TableGuid, + IN OUT VOID **Table + ); + +BOOLEAN +LibIsValidTextGraphics ( + IN CHAR16 Graphic, + OUT CHAR8 *PcAnsi, OPTIONAL + OUT CHAR8 *Ascii OPTIONAL + ); + +BOOLEAN +IsValidAscii ( + IN CHAR16 Ascii + ); + +BOOLEAN +IsValidEfiCntlChar ( + IN CHAR16 c + ); + +CHAR16 * +LibGetUiString ( + IN EFI_HANDLE Handle, + IN UI_STRING_TYPE StringType, + IN ISO_639_2 *LangCode, + IN BOOLEAN ReturnDevicePathStrOnMismatch + ); + +CHAR8* +LibGetSmbiosString ( + IN SMBIOS_STRUCTURE_POINTER *Smbios, + IN UINT16 StringNumber + ); + +EFI_STATUS +LibGetSmbiosSystemGuidAndSerialNumber ( + IN EFI_GUID *SystemGuid, + OUT CHAR8 **SystemSerialNumber + ); + + +EFI_STATUS +InitializeGlobalIoDevice ( + IN EFI_DEVICE_PATH *DevicePath, + IN EFI_GUID *Protocol, + IN CHAR8 *ErrorStr, + OUT EFI_DEVICE_IO_INTERFACE **GlobalIoFncs + ); + +UINT32 +ReadPort ( + IN EFI_DEVICE_IO_INTERFACE *GlobalIoFncs, + IN EFI_IO_WIDTH Width, + IN UINTN Port + ); + +UINT32 +WritePort ( + IN EFI_DEVICE_IO_INTERFACE *GlobalIoFncs, + IN EFI_IO_WIDTH Width, + IN UINTN Port, + IN UINTN Data + ); + +UINT32 +ReadPciConfig ( + IN EFI_DEVICE_IO_INTERFACE *GlobalIoFncs, + IN EFI_IO_WIDTH Width, + IN UINTN Port + ); + +UINT32 +WritePciConfig ( + IN EFI_DEVICE_IO_INTERFACE *GlobalIoFncs, + IN EFI_IO_WIDTH Width, + IN UINTN Port, + IN UINTN Data + ); + +extern EFI_DEVICE_IO_INTERFACE *GlobalIoFncs; + +#define outp(_Port, _DataByte) (UINT8)WritePort(GlobalIoFncs, IO_UINT8, (UINTN)_Port, (UINTN)_DataByte) +#define inp(_Port) (UINT8)ReadPort(GlobalIoFncs, IO_UINT8, (UINTN)_Port) +#define outpw(_Port, _DataByte) (UINT16)WritePort(GlobalIoFncs, IO_UINT16, (UINTN)_Port, (UINTN)_DataByte) +#define inpw(_Port) (UINT16)ReadPort(GlobalIoFncs, IO_UINT16, (UINTN)_Port) +#define outpd(_Port, _DataByte) (UINT32)WritePort(GlobalIoFncs, IO_UINT32, (UINTN)_Port, (UINTN)_DataByte) +#define inpd(_Port) (UINT32)ReadPort(GlobalIoFncs, IO_UINT32, (UINTN)_Port) + +#define writepci8(_Addr, _DataByte) (UINT8)WritePciConfig(GlobalIoFncs, IO_UINT8, (UINTN)_Addr, (UINTN)_DataByte) +#define readpci8(_Addr) (UINT8)ReadPciConfig(GlobalIoFncs, IO_UINT8, (UINTN)_Addr) +#define writepci16(_Addr, _DataByte) (UINT16)WritePciConfig(GlobalIoFncs, IO_UINT16, (UINTN)_Addr, (UINTN)_DataByte) +#define readpci16(_Addr) (UINT16)ReadPciConfig(GlobalIoFncs, IO_UINT16, (UINTN)_Addr) +#define writepci32(_Addr, _DataByte) (UINT32)WritePciConfig(GlobalIoFncs, IO_UINT32, (UINTN)_Addr, (UINTN)_DataByte) +#define readpci32(_Addr) (UINT32)ReadPciConfig(GlobalIoFncs, IO_UINT32, (UINTN)_Addr) + +#define Pause() WaitForSingleEvent (ST->ConIn->WaitForKey, 0) +#define Port80(_PostCode) GlobalIoFncs->Io.Write (GlobalIoFncs, IO_UINT16, (UINT64)0x80, 1, &(_PostCode)) + +#endif diff --git a/gnu-efi/inc/efilink.h b/gnu-efi/inc/efilink.h new file mode 100644 index 0000000..cc5aa2d --- /dev/null +++ b/gnu-efi/inc/efilink.h @@ -0,0 +1,177 @@ +#ifndef _EFI_LINK_H +#define _EFI_LINK_H + +/*++ + +Copyright (c) 1998 Intel Corporation + +Module Name: + + link.h (renamed efilink.h to avoid conflicts) + +Abstract: + + EFI link list macro's + + + +Revision History + +--*/ + +#ifndef EFI_NT_EMUL + +// +// List entry - doubly linked list +// + +typedef struct _LIST_ENTRY { + struct _LIST_ENTRY *Flink; + struct _LIST_ENTRY *Blink; +} LIST_ENTRY; + +#endif + + +// +// VOID +// InitializeListHead( +// LIST_ENTRY *ListHead +// ); +// + +#define InitializeListHead(ListHead) \ + (ListHead)->Flink = ListHead; \ + (ListHead)->Blink = ListHead; + +// +// BOOLEAN +// IsListEmpty( +// PLIST_ENTRY ListHead +// ); +// + +#define IsListEmpty(ListHead) \ + ((ListHead)->Flink == (ListHead)) + +// +// VOID +// RemoveEntryList( +// PLIST_ENTRY Entry +// ); +// + +#define _RemoveEntryList(Entry) { \ + LIST_ENTRY *_Blink, *_Flink; \ + _Flink = (Entry)->Flink; \ + _Blink = (Entry)->Blink; \ + _Blink->Flink = _Flink; \ + _Flink->Blink = _Blink; \ + } + +#if EFI_DEBUG + #define RemoveEntryList(Entry) \ + _RemoveEntryList(Entry); \ + (Entry)->Flink = (LIST_ENTRY *) BAD_POINTER; \ + (Entry)->Blink = (LIST_ENTRY *) BAD_POINTER; +#else + #define RemoveEntryList(Entry) \ + _RemoveEntryList(Entry); +#endif + +// +// VOID +// InsertTailList( +// PLIST_ENTRY ListHead, +// PLIST_ENTRY Entry +// ); +// + +#define InsertTailList(ListHead,Entry) {\ + LIST_ENTRY *_ListHead, *_Blink; \ + _ListHead = (ListHead); \ + _Blink = _ListHead->Blink; \ + (Entry)->Flink = _ListHead; \ + (Entry)->Blink = _Blink; \ + _Blink->Flink = (Entry); \ + _ListHead->Blink = (Entry); \ + } + +// +// VOID +// InsertHeadList( +// PLIST_ENTRY ListHead, +// PLIST_ENTRY Entry +// ); +// + +#define InsertHeadList(ListHead,Entry) {\ + LIST_ENTRY *_ListHead, *_Flink; \ + _ListHead = (ListHead); \ + _Flink = _ListHead->Flink; \ + (Entry)->Flink = _Flink; \ + (Entry)->Blink = _ListHead; \ + _Flink->Blink = (Entry); \ + _ListHead->Flink = (Entry); \ + } + +// VOID +// SwapListEntries( +// PLIST_ENTRY Entry1, +// PLIST_ENTRY Entry2 +// ); +// +// Put Entry2 before Entry1 +// +#define SwapListEntries(Entry1,Entry2) {\ + LIST_ENTRY *Entry1Flink, *Entry1Blink; \ + LIST_ENTRY *Entry2Flink, *Entry2Blink; \ + Entry2Flink = (Entry2)->Flink; \ + Entry2Blink = (Entry2)->Blink; \ + Entry1Flink = (Entry1)->Flink; \ + Entry1Blink = (Entry1)->Blink; \ + Entry2Blink->Flink = Entry2Flink; \ + Entry2Flink->Blink = Entry2Blink; \ + (Entry2)->Flink = Entry1; \ + (Entry2)->Blink = Entry1Blink; \ + Entry1Blink->Flink = (Entry2); \ + (Entry1)->Blink = (Entry2); \ + } + +// +// EFI_FIELD_OFFSET - returns the byte offset to a field within a structure +// + +#define EFI_FIELD_OFFSET(TYPE,Field) ((UINTN)(intptr_t)(&(((TYPE *) 0)->Field))) + +// +// CONTAINING_RECORD - returns a pointer to the structure +// from one of it's elements. +// + +#define _CR(Record, TYPE, Field) \ + ((TYPE *) ( (CHAR8 *)(Record) - (CHAR8 *) &(((TYPE *) 0)->Field))) + +#if EFI_DEBUG + #define CR(Record, TYPE, Field, Sig) \ + _CR(Record, TYPE, Field)->Signature != Sig ? \ + (TYPE *) ASSERT_STRUCT(_CR(Record, TYPE, Field), Record) : \ + _CR(Record, TYPE, Field) +#else + #define CR(Record, TYPE, Field, Signature) \ + _CR(Record, TYPE, Field) +#endif + + +// +// A lock structure +// + +typedef struct _FLOCK { + EFI_TPL Tpl; + EFI_TPL OwnerTpl; + UINTN Lock; +} FLOCK; + +#endif + diff --git a/gnu-efi/inc/efinet.h b/gnu-efi/inc/efinet.h new file mode 100644 index 0000000..6215816 --- /dev/null +++ b/gnu-efi/inc/efinet.h @@ -0,0 +1,348 @@ +#ifndef _EFINET_H +#define _EFINET_H + + +/*++ +Copyright (c) 1999 Intel Corporation + +Module Name: + efinet.h + +Abstract: + EFI Simple Network protocol + +Revision History +--*/ + + +/////////////////////////////////////////////////////////////////////////////// +// +// Simple Network Protocol +// + +#define EFI_SIMPLE_NETWORK_PROTOCOL_GUID \ + { 0xA19832B9, 0xAC25, 0x11D3, {0x9A, 0x2D, 0x00, 0x90, 0x27, 0x3F, 0xC1, 0x4D} } + +INTERFACE_DECL(_EFI_SIMPLE_NETWORK_PROTOCOL); + +/////////////////////////////////////////////////////////////////////////////// +// + +typedef struct { + // + // Total number of frames received. Includes frames with errors and + // dropped frames. + // + UINT64 RxTotalFrames; + + // + // Number of valid frames received and copied into receive buffers. + // + UINT64 RxGoodFrames; + + // + // Number of frames below the minimum length for the media. + // This would be <64 for ethernet. + // + UINT64 RxUndersizeFrames; + + // + // Number of frames longer than the maxminum length for the + // media. This would be >1500 for ethernet. + // + UINT64 RxOversizeFrames; + + // + // Valid frames that were dropped because receive buffers were full. + // + UINT64 RxDroppedFrames; + + // + // Number of valid unicast frames received and not dropped. + // + UINT64 RxUnicastFrames; + + // + // Number of valid broadcast frames received and not dropped. + // + UINT64 RxBroadcastFrames; + + // + // Number of valid mutlicast frames received and not dropped. + // + UINT64 RxMulticastFrames; + + // + // Number of frames w/ CRC or alignment errors. + // + UINT64 RxCrcErrorFrames; + + // + // Total number of bytes received. Includes frames with errors + // and dropped frames. + // + UINT64 RxTotalBytes; + + // + // Transmit statistics. + // + UINT64 TxTotalFrames; + UINT64 TxGoodFrames; + UINT64 TxUndersizeFrames; + UINT64 TxOversizeFrames; + UINT64 TxDroppedFrames; + UINT64 TxUnicastFrames; + UINT64 TxBroadcastFrames; + UINT64 TxMulticastFrames; + UINT64 TxCrcErrorFrames; + UINT64 TxTotalBytes; + + // + // Number of collisions detection on this subnet. + // + UINT64 Collisions; + + // + // Number of frames destined for unsupported protocol. + // + UINT64 UnsupportedProtocol; + +} EFI_NETWORK_STATISTICS; + +/////////////////////////////////////////////////////////////////////////////// +// + +typedef enum { + EfiSimpleNetworkStopped, + EfiSimpleNetworkStarted, + EfiSimpleNetworkInitialized, + EfiSimpleNetworkMaxState +} EFI_SIMPLE_NETWORK_STATE; + +/////////////////////////////////////////////////////////////////////////////// +// + +#define EFI_SIMPLE_NETWORK_RECEIVE_UNICAST 0x01 +#define EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST 0x02 +#define EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST 0x04 +#define EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS 0x08 +#define EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST 0x10 + +/////////////////////////////////////////////////////////////////////////////// +// + +#define EFI_SIMPLE_NETWORK_RECEIVE_INTERRUPT 0x01 +#define EFI_SIMPLE_NETWORK_TRANSMIT_INTERRUPT 0x02 +#define EFI_SIMPLE_NETWORK_COMMAND_INTERRUPT 0x04 +#define EFI_SIMPLE_NETWORK_SOFTWARE_INTERRUPT 0x08 + +/////////////////////////////////////////////////////////////////////////////// +// +#define MAX_MCAST_FILTER_CNT 16 +typedef struct { + UINT32 State; + UINT32 HwAddressSize; + UINT32 MediaHeaderSize; + UINT32 MaxPacketSize; + UINT32 NvRamSize; + UINT32 NvRamAccessSize; + UINT32 ReceiveFilterMask; + UINT32 ReceiveFilterSetting; + UINT32 MaxMCastFilterCount; + UINT32 MCastFilterCount; + EFI_MAC_ADDRESS MCastFilter[MAX_MCAST_FILTER_CNT]; + EFI_MAC_ADDRESS CurrentAddress; + EFI_MAC_ADDRESS BroadcastAddress; + EFI_MAC_ADDRESS PermanentAddress; + UINT8 IfType; + BOOLEAN MacAddressChangeable; + BOOLEAN MultipleTxSupported; + BOOLEAN MediaPresentSupported; + BOOLEAN MediaPresent; +} EFI_SIMPLE_NETWORK_MODE; + +/////////////////////////////////////////////////////////////////////////////// +// + +typedef +EFI_STATUS +(EFIAPI *EFI_SIMPLE_NETWORK_START) ( + IN struct _EFI_SIMPLE_NETWORK_PROTOCOL *This +); + +/////////////////////////////////////////////////////////////////////////////// +// + +typedef +EFI_STATUS +(EFIAPI *EFI_SIMPLE_NETWORK_STOP) ( + IN struct _EFI_SIMPLE_NETWORK_PROTOCOL *This +); + +/////////////////////////////////////////////////////////////////////////////// +// + +typedef +EFI_STATUS +(EFIAPI *EFI_SIMPLE_NETWORK_INITIALIZE) ( + IN struct _EFI_SIMPLE_NETWORK_PROTOCOL *This, + IN UINTN ExtraRxBufferSize OPTIONAL, + IN UINTN ExtraTxBufferSize OPTIONAL +); + +/////////////////////////////////////////////////////////////////////////////// +// + +typedef +EFI_STATUS +(EFIAPI *EFI_SIMPLE_NETWORK_RESET) ( + IN struct _EFI_SIMPLE_NETWORK_PROTOCOL *This, + IN BOOLEAN ExtendedVerification +); + +/////////////////////////////////////////////////////////////////////////////// +// + +typedef +EFI_STATUS +(EFIAPI *EFI_SIMPLE_NETWORK_SHUTDOWN) ( + IN struct _EFI_SIMPLE_NETWORK_PROTOCOL *This +); + +/////////////////////////////////////////////////////////////////////////////// +// + +typedef +EFI_STATUS +(EFIAPI *EFI_SIMPLE_NETWORK_RECEIVE_FILTERS) ( + IN struct _EFI_SIMPLE_NETWORK_PROTOCOL *This, + IN UINT32 Enable, + IN UINT32 Disable, + IN BOOLEAN ResetMCastFilter, + IN UINTN MCastFilterCnt OPTIONAL, + IN EFI_MAC_ADDRESS *MCastFilter OPTIONAL +); + +/////////////////////////////////////////////////////////////////////////////// +// + +typedef +EFI_STATUS +(EFIAPI *EFI_SIMPLE_NETWORK_STATION_ADDRESS) ( + IN struct _EFI_SIMPLE_NETWORK_PROTOCOL *This, + IN BOOLEAN Reset, + IN EFI_MAC_ADDRESS *New OPTIONAL +); + +/////////////////////////////////////////////////////////////////////////////// +// + +typedef +EFI_STATUS +(EFIAPI *EFI_SIMPLE_NETWORK_STATISTICS) ( + IN struct _EFI_SIMPLE_NETWORK_PROTOCOL *This, + IN BOOLEAN Reset, + IN OUT UINTN *StatisticsSize OPTIONAL, + OUT EFI_NETWORK_STATISTICS *StatisticsTable OPTIONAL +); + +/////////////////////////////////////////////////////////////////////////////// +// + +typedef +EFI_STATUS +(EFIAPI *EFI_SIMPLE_NETWORK_MCAST_IP_TO_MAC) ( + IN struct _EFI_SIMPLE_NETWORK_PROTOCOL *This, + IN BOOLEAN IPv6, + IN EFI_IP_ADDRESS *IP, + OUT EFI_MAC_ADDRESS *MAC +); + +/////////////////////////////////////////////////////////////////////////////// +// + +typedef +EFI_STATUS +(EFIAPI *EFI_SIMPLE_NETWORK_NVDATA) ( + IN struct _EFI_SIMPLE_NETWORK_PROTOCOL *This, + IN BOOLEAN ReadWrite, + IN UINTN Offset, + IN UINTN BufferSize, + IN OUT VOID *Buffer +); + +/////////////////////////////////////////////////////////////////////////////// +// + +typedef +EFI_STATUS +(EFIAPI *EFI_SIMPLE_NETWORK_GET_STATUS) ( + IN struct _EFI_SIMPLE_NETWORK_PROTOCOL *This, + OUT UINT32 *InterruptStatus OPTIONAL, + OUT VOID **TxBuf OPTIONAL +); + +/////////////////////////////////////////////////////////////////////////////// +// + +typedef +EFI_STATUS +(EFIAPI *EFI_SIMPLE_NETWORK_TRANSMIT) ( + IN struct _EFI_SIMPLE_NETWORK_PROTOCOL *This, + IN UINTN HeaderSize, + IN UINTN BufferSize, + IN VOID *Buffer, + IN EFI_MAC_ADDRESS *SrcAddr OPTIONAL, + IN EFI_MAC_ADDRESS *DestAddr OPTIONAL, + IN UINT16 *Protocol OPTIONAL +); + +/////////////////////////////////////////////////////////////////////////////// +// + +typedef +EFI_STATUS +(EFIAPI *EFI_SIMPLE_NETWORK_RECEIVE) ( + IN struct _EFI_SIMPLE_NETWORK_PROTOCOL *This, + OUT UINTN *HeaderSize OPTIONAL, + IN OUT UINTN *BufferSize, + OUT VOID *Buffer, + OUT EFI_MAC_ADDRESS *SrcAddr OPTIONAL, + OUT EFI_MAC_ADDRESS *DestAddr OPTIONAL, + OUT UINT16 *Protocol OPTIONAL +); + +/////////////////////////////////////////////////////////////////////////////// +// + +#define EFI_SIMPLE_NETWORK_PROTOCOL_REVISION 0x00010000 +#define EFI_SIMPLE_NETWORK_INTERFACE_REVISION EFI_SIMPLE_NETWORK_PROTOCOL_REVISION + +typedef struct _EFI_SIMPLE_NETWORK_PROTOCOL { + UINT64 Revision; + EFI_SIMPLE_NETWORK_START Start; + EFI_SIMPLE_NETWORK_STOP Stop; + EFI_SIMPLE_NETWORK_INITIALIZE Initialize; + EFI_SIMPLE_NETWORK_RESET Reset; + EFI_SIMPLE_NETWORK_SHUTDOWN Shutdown; + EFI_SIMPLE_NETWORK_RECEIVE_FILTERS ReceiveFilters; + EFI_SIMPLE_NETWORK_STATION_ADDRESS StationAddress; + EFI_SIMPLE_NETWORK_STATISTICS Statistics; + EFI_SIMPLE_NETWORK_MCAST_IP_TO_MAC MCastIpToMac; + EFI_SIMPLE_NETWORK_NVDATA NvData; + EFI_SIMPLE_NETWORK_GET_STATUS GetStatus; + EFI_SIMPLE_NETWORK_TRANSMIT Transmit; + EFI_SIMPLE_NETWORK_RECEIVE Receive; + EFI_EVENT WaitForPacket; + EFI_SIMPLE_NETWORK_MODE *Mode; +} EFI_SIMPLE_NETWORK_PROTOCOL; + +// Note: Because it conflicted with the EDK2 struct name, the +// 'EFI_SIMPLE_NETWORK_PROTOCOL' GUID definition, from older +// versions of gnu-efi, is now obsoleted. +// Use 'EFI_SIMPLE_NETWORK_PROTOCOL_GUID' instead. + +typedef struct _EFI_SIMPLE_NETWORK_PROTOCOL _EFI_SIMPLE_NETWORK; +typedef EFI_SIMPLE_NETWORK_PROTOCOL EFI_SIMPLE_NETWORK; + +#endif /* _EFINET_H */ diff --git a/gnu-efi/inc/efipart.h b/gnu-efi/inc/efipart.h new file mode 100644 index 0000000..d4c5573 --- /dev/null +++ b/gnu-efi/inc/efipart.h @@ -0,0 +1,61 @@ +#ifndef _EFI_PART_H +#define _EFI_PART_H + +/*++ + +Copyright (c) 1998 Intel Corporation + +Module Name: + + efipart.h + +Abstract: + Info about disk partitions and Master Boot Records + + + + +Revision History + +--*/ + +// +// +// + +#define EFI_PARTITION 0xef +#define MBR_SIZE 512 + +#pragma pack(1) + +typedef struct { + UINT8 BootIndicator; + UINT8 StartHead; + UINT8 StartSector; + UINT8 StartTrack; + UINT8 OSIndicator; + UINT8 EndHead; + UINT8 EndSector; + UINT8 EndTrack; + UINT8 StartingLBA[4]; + UINT8 SizeInLBA[4]; +} MBR_PARTITION_RECORD; + +#define EXTRACT_UINT32(D) (UINT32)(D[0] | (D[1] << 8) | (D[2] << 16) | (D[3] << 24)) + +#define MBR_SIGNATURE 0xaa55 +#define MIN_MBR_DEVICE_SIZE 0x80000 +#define MBR_ERRATA_PAD 0x40000 // 128 MB + +#define MAX_MBR_PARTITIONS 4 +typedef struct { + UINT8 BootStrapCode[440]; + UINT8 UniqueMbrSignature[4]; + UINT8 Unknown[2]; + MBR_PARTITION_RECORD Partition[MAX_MBR_PARTITIONS]; + UINT16 Signature; +} MASTER_BOOT_RECORD; +#pragma pack() + + +#endif diff --git a/gnu-efi/inc/efipciio.h b/gnu-efi/inc/efipciio.h new file mode 100644 index 0000000..e885387 --- /dev/null +++ b/gnu-efi/inc/efipciio.h @@ -0,0 +1,399 @@ +#ifndef _EFI_PCI_IO_H +#define _EFI_PCI_IO_H + +#define EFI_PCI_IO_PROTOCOL_GUID \ + { 0x4cf5b200, 0x68b8, 0x4ca5, {0x9e, 0xec, 0xb2, 0x3e, 0x3f, 0x50, 0x02, 0x9a} } + +#define EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_GUID \ + { 0x2f707ebb, 0x4a1a, 0x11d4, {0x9a, 0x38, 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d} } + +INTERFACE_DECL(_EFI_PCI_IO_PROTOCOL); +INTERFACE_DECL(_EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL); + +typedef enum { + EfiPciIoWidthUint8, + EfiPciIoWidthUint16, + EfiPciIoWidthUint32, + EfiPciIoWidthUint64, + EfiPciIoWidthFifoUint8, + EfiPciIoWidthFifoUint16, + EfiPciIoWidthFifoUint32, + EfiPciIoWidthFifoUint64, + EfiPciIoWidthFillUint8, + EfiPciIoWidthFillUint16, + EfiPciIoWidthFillUint32, + EfiPciIoWidthFillUint64, + EfiPciIoWidthMaximum +} EFI_PCI_IO_PROTOCOL_WIDTH, EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH; + +#define EFI_PCI_IO_PASS_THROUGH_BAR 0xff + +typedef +EFI_STATUS +(EFIAPI *EFI_PCI_IO_PROTOCOL_POLL_IO_MEM) ( + IN struct _EFI_PCI_IO_PROTOCOL *This, + IN EFI_PCI_IO_PROTOCOL_WIDTH Width, + IN UINT8 BarIndex, + IN UINT64 Offset, + IN UINT64 Mask, + IN UINT64 Value, + IN UINT64 Delay, + OUT UINT64 *Result +); + +typedef +EFI_STATUS +(EFIAPI *EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_POLL_IO_MEM) ( + IN struct _EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width, + IN UINT64 Address, + IN UINT64 Mask, + IN UINT64 Value, + IN UINT64 Delay, + OUT UINT64 *Result +); + +typedef +EFI_STATUS +(EFIAPI *EFI_PCI_IO_PROTOCOL_IO_MEM) ( + IN struct _EFI_PCI_IO_PROTOCOL *This, + IN EFI_PCI_IO_PROTOCOL_WIDTH Width, + IN UINT8 BarIndex, + IN UINT64 Offset, + IN UINTN Count, + IN OUT VOID *Buffer +); + +typedef +EFI_STATUS +(EFIAPI *EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_IO_MEM) ( + IN struct _EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width, + IN UINT64 Address, + IN UINTN Count, + IN OUT VOID *Buffer +); + +typedef struct { + EFI_PCI_IO_PROTOCOL_IO_MEM Read; + EFI_PCI_IO_PROTOCOL_IO_MEM Write; +} EFI_PCI_IO_PROTOCOL_ACCESS; + +typedef struct { + EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_IO_MEM Read; + EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_IO_MEM Write; +} EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_ACCESS; + +typedef +EFI_STATUS +(EFIAPI *EFI_PCI_IO_PROTOCOL_CONFIG) ( + IN struct _EFI_PCI_IO_PROTOCOL *This, + IN EFI_PCI_IO_PROTOCOL_WIDTH Width, + IN UINT32 Offset, + IN UINTN Count, + IN OUT VOID *Buffer +); + +typedef +EFI_STATUS +(EFIAPI *EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_CONFIGURATION) ( + IN struct _EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, + OUT VOID **Resources +); + +typedef struct { + EFI_PCI_IO_PROTOCOL_CONFIG Read; + EFI_PCI_IO_PROTOCOL_CONFIG Write; +} EFI_PCI_IO_PROTOCOL_CONFIG_ACCESS; + +typedef +EFI_STATUS +(EFIAPI *EFI_PCI_IO_PROTOCOL_COPY_MEM) ( + IN struct _EFI_PCI_IO_PROTOCOL *This, + IN EFI_PCI_IO_PROTOCOL_WIDTH Width, + IN UINT8 DestBarIndex, + IN UINT64 DestOffset, + IN UINT8 SrcBarIndex, + IN UINT64 SrcOffset, + IN UINTN Count +); + +typedef +EFI_STATUS +(EFIAPI *EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_COPY_MEM) ( + IN struct _EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width, + IN UINT64 DestAddress, + IN UINT64 SrcAddress, + IN UINTN Count +); + +typedef enum { + EfiPciIoOperationBusMasterRead, + EfiPciIoOperationBusMasterWrite, + EfiPciIoOperationBusMasterCommonBuffer, + EfiPciIoOperationMaximum +} EFI_PCI_IO_PROTOCOL_OPERATION; + +typedef enum { + EfiPciOperationBusMasterRead, + EfiPciOperationBusMasterWrite, + EfiPciOperationBusMasterCommonBuffer, + EfiPciOperationBusMasterRead64, + EfiPciOperationBusMasterWrite64, + EfiPciOperationBusMasterCommonBuffer64, + EfiPciOperationMaximum +} EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION; + +typedef +EFI_STATUS +(EFIAPI *EFI_PCI_IO_PROTOCOL_MAP) ( + IN struct _EFI_PCI_IO_PROTOCOL *This, + IN EFI_PCI_IO_PROTOCOL_OPERATION Operation, + IN VOID *HostAddress, + IN OUT UINTN *NumberOfBytes, + OUT EFI_PHYSICAL_ADDRESS *DeviceAddress, + OUT VOID **Mapping +); + +typedef +EFI_STATUS +(EFIAPI *EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_MAP) ( + IN struct _EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION Operation, + IN VOID *HostAddress, + IN OUT UINTN *NumberOfBytes, + OUT EFI_PHYSICAL_ADDRESS *DeviceAddress, + OUT VOID **Mapping +); + +typedef +EFI_STATUS +(EFIAPI *EFI_PCI_IO_PROTOCOL_UNMAP) ( + IN struct _EFI_PCI_IO_PROTOCOL *This, + IN VOID *Mapping +); + +typedef +EFI_STATUS +(EFIAPI *EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_UNMAP) ( + IN struct _EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, + IN VOID *Mapping +); + +typedef +EFI_STATUS +(EFIAPI *EFI_PCI_IO_PROTOCOL_ALLOCATE_BUFFER) ( + IN struct _EFI_PCI_IO_PROTOCOL *This, + IN EFI_ALLOCATE_TYPE Type, + IN EFI_MEMORY_TYPE MemoryType, + IN UINTN Pages, + OUT VOID **HostAddress, + IN UINT64 Attributes +); + +typedef +EFI_STATUS +(EFIAPI *EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_ALLOCATE_BUFFER) ( + IN struct _EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, + IN EFI_ALLOCATE_TYPE Type, + IN EFI_MEMORY_TYPE MemoryType, + IN UINTN Pages, + IN OUT VOID **HostAddress, + IN UINT64 Attributes +); + +typedef +EFI_STATUS +(EFIAPI *EFI_PCI_IO_PROTOCOL_FREE_BUFFER) ( + IN struct _EFI_PCI_IO_PROTOCOL *This, + IN UINTN Pages, + IN VOID *HostAddress + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_FREE_BUFFER) ( + IN struct _EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, + IN UINTN Pages, + IN VOID *HostAddress +); + +typedef +EFI_STATUS +(EFIAPI *EFI_PCI_IO_PROTOCOL_FLUSH) ( + IN struct _EFI_PCI_IO_PROTOCOL *This +); + +typedef +EFI_STATUS +(EFIAPI *EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_FLUSH) ( + IN struct _EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This +); + +typedef +EFI_STATUS +(EFIAPI *EFI_PCI_IO_PROTOCOL_GET_LOCATION) ( + IN struct _EFI_PCI_IO_PROTOCOL *This, + OUT UINTN *SegmentNumber, + OUT UINTN *BusNumber, + OUT UINTN *DeviceNumber, + OUT UINTN *FunctionNumber +); + +#define EFI_PCI_ATTRIBUTE_ISA_MOTHERBOARD_IO 0x0001 +#define EFI_PCI_ATTRIBUTE_ISA_IO 0x0002 +#define EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO 0x0004 +#define EFI_PCI_ATTRIBUTE_VGA_MEMORY 0x0008 +#define EFI_PCI_ATTRIBUTE_VGA_IO 0x0010 +#define EFI_PCI_ATTRIBUTE_IDE_PRIMARY_IO 0x0020 +#define EFI_PCI_ATTRIBUTE_IDE_SECONDARY_IO 0x0040 +#define EFI_PCI_ATTRIBUTE_MEMORY_WRITE_COMBINE 0x0080 +#define EFI_PCI_ATTRIBUTE_IO 0x0100 +#define EFI_PCI_ATTRIBUTE_MEMORY 0x0200 +#define EFI_PCI_ATTRIBUTE_BUS_MASTER 0x0400 +#define EFI_PCI_ATTRIBUTE_MEMORY_CACHED 0x0800 +#define EFI_PCI_ATTRIBUTE_MEMORY_DISABLE 0x1000 +#define EFI_PCI_ATTRIBUTE_EMBEDDED_DEVICE 0x2000 +#define EFI_PCI_ATTRIBUTE_EMBEDDED_ROM 0x4000 +#define EFI_PCI_ATTRIBUTE_DUAL_ADDRESS_CYCLE 0x8000 +#define EFI_PCI_ATTRIBUTE_ISA_IO_16 0x10000 +#define EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO_16 0x20000 +#define EFI_PCI_ATTRIBUTE_VGA_IO_16 0x40000 + +#define EFI_PCI_IO_ATTRIBUTE_ISA_MOTHERBOARD_IO EFI_PCI_ATTRIBUTE_ISA_MOTHERBOARD_IO +#define EFI_PCI_IO_ATTRIBUTE_ISA_IO EFI_PCI_ATTRIBUTE_ISA_IO +#define EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO +#define EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY EFI_PCI_ATTRIBUTE_VGA_MEMORY +#define EFI_PCI_IO_ATTRIBUTE_VGA_IO EFI_PCI_ATTRIBUTE_VGA_IO +#define EFI_PCI_IO_ATTRIBUTE_IDE_PRIMARY_IO EFI_PCI_ATTRIBUTE_IDE_PRIMARY_IO +#define EFI_PCI_IO_ATTRIBUTE_IDE_SECONDARY_IO EFI_PCI_ATTRIBUTE_IDE_SECONDARY_IO +#define EFI_PCI_IO_ATTRIBUTE_MEMORY_WRITE_COMBINE EFI_PCI_ATTRIBUTE_MEMORY_WRITE_COMBINE +#define EFI_PCI_IO_ATTRIBUTE_IO EFI_PCI_ATTRIBUTE_IO +#define EFI_PCI_IO_ATTRIBUTE_MEMORY EFI_PCI_ATTRIBUTE_MEMORY +#define EFI_PCI_IO_ATTRIBUTE_BUS_MASTER EFI_PCI_ATTRIBUTE_BUS_MASTER +#define EFI_PCI_IO_ATTRIBUTE_MEMORY_CACHED EFI_PCI_ATTRIBUTE_MEMORY_CACHED +#define EFI_PCI_IO_ATTRIBUTE_MEMORY_DISABLE EFI_PCI_ATTRIBUTE_MEMORY_DISABLE +#define EFI_PCI_IO_ATTRIBUTE_EMBEDDED_DEVICE EFI_PCI_ATTRIBUTE_EMBEDDED_DEVICE +#define EFI_PCI_IO_ATTRIBUTE_EMBEDDED_ROM EFI_PCI_ATTRIBUTE_EMBEDDED_ROM +#define EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE EFI_PCI_ATTRIBUTE_DUAL_ADDRESS_CYCLE +#define EFI_PCI_IO_ATTRIBUTE_ISA_IO_16 EFI_PCI_ATTRIBUTE_ISA_IO_16 +#define EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO_16 EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO_16 +#define EFI_PCI_IO_ATTRIBUTE_VGA_IO_16 EFI_PCI_ATTRIBUTE_VGA_IO_16 + +#define EFI_PCI_ATTRIBUTE_VALID_FOR_ALLOCATE_BUFFER \ + (EFI_PCI_ATTRIBUTE_MEMORY_WRITE_COMBINE | EFI_PCI_ATTRIBUTE_MEMORY_CACHED | EFI_PCI_ATTRIBUTE_DUAL_ADDRESS_CYCLE) + +#define EFI_PCI_ATTRIBUTE_INVALID_FOR_ALLOCATE_BUFFER \ + (~EFI_PCI_ATTRIBUTE_VALID_FOR_ALLOCATE_BUFFER) + +typedef struct { + UINT8 Register; + UINT8 Function; + UINT8 Device; + UINT8 Bus; + UINT32 ExtendedRegister; +} EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS; + +typedef enum { + EfiPciIoAttributeOperationGet, + EfiPciIoAttributeOperationSet, + EfiPciIoAttributeOperationEnable, + EfiPciIoAttributeOperationDisable, + EfiPciIoAttributeOperationSupported, + EfiPciIoAttributeOperationMaximum +} EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION; + +typedef +EFI_STATUS +(EFIAPI *EFI_PCI_IO_PROTOCOL_ATTRIBUTES) ( + IN struct _EFI_PCI_IO_PROTOCOL *This, + IN EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION Operation, + IN UINT64 Attributes, + OUT UINT64 *Result OPTIONAL +); + +typedef +EFI_STATUS +(EFIAPI *EFI_PCI_IO_PROTOCOL_GET_BAR_ATTRIBUTES) ( + IN struct _EFI_PCI_IO_PROTOCOL *This, + IN UINT8 BarIndex, + OUT UINT64 *Supports OPTIONAL, + OUT VOID **Resources OPTIONAL +); + +typedef +EFI_STATUS +(EFIAPI *EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_GET_ATTRIBUTES) ( + IN struct _EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, + OUT UINT64 *Supports, + OUT UINT64 *Attributes +); + +typedef +EFI_STATUS +(EFIAPI *EFI_PCI_IO_PROTOCOL_SET_BAR_ATTRIBUTES) ( + IN struct _EFI_PCI_IO_PROTOCOL *This, + IN UINT64 Attributes, + IN UINT8 BarIndex, + IN OUT UINT64 *Offset, + IN OUT UINT64 *Length +); + +typedef +EFI_STATUS +(EFIAPI *EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_SET_ATTRIBUTES) ( + IN struct _EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This, + IN UINT64 Attributes, + IN OUT UINT64 *ResourceBase, + IN OUT UINT64 *ResourceLength +); + +typedef struct _EFI_PCI_IO_PROTOCOL { + EFI_PCI_IO_PROTOCOL_POLL_IO_MEM PollMem; + EFI_PCI_IO_PROTOCOL_POLL_IO_MEM PollIo; + EFI_PCI_IO_PROTOCOL_ACCESS Mem; + EFI_PCI_IO_PROTOCOL_ACCESS Io; + EFI_PCI_IO_PROTOCOL_CONFIG_ACCESS Pci; + EFI_PCI_IO_PROTOCOL_COPY_MEM CopyMem; + EFI_PCI_IO_PROTOCOL_MAP Map; + EFI_PCI_IO_PROTOCOL_UNMAP Unmap; + EFI_PCI_IO_PROTOCOL_ALLOCATE_BUFFER AllocateBuffer; + EFI_PCI_IO_PROTOCOL_FREE_BUFFER FreeBuffer; + EFI_PCI_IO_PROTOCOL_FLUSH Flush; + EFI_PCI_IO_PROTOCOL_GET_LOCATION GetLocation; + EFI_PCI_IO_PROTOCOL_ATTRIBUTES Attributes; + EFI_PCI_IO_PROTOCOL_GET_BAR_ATTRIBUTES GetBarAttributes; + EFI_PCI_IO_PROTOCOL_SET_BAR_ATTRIBUTES SetBarAttributes; + UINT64 RomSize; + VOID *RomImage; +} EFI_PCI_IO_PROTOCOL; + +// Note: Because it conflicted with the EDK2 struct name, the +// 'EFI_PCI_IO_PROTOCOL' GUID definition, from older versions +// of gnu-efi, is now obsoleted. +// Use 'EFI_PCI_IO_PROTOCOL_GUID' instead. + +typedef struct _EFI_PCI_IO_PROTOCOL _EFI_PCI_IO; +typedef EFI_PCI_IO_PROTOCOL EFI_PCI_IO; + +typedef struct _EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL { + EFI_HANDLE ParentHandle; + EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_POLL_IO_MEM PollMem; + EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_POLL_IO_MEM PollIo; + EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_ACCESS Mem; + EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_ACCESS Io; + EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_ACCESS Pci; + EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_COPY_MEM CopyMem; + EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_MAP Map; + EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_UNMAP Unmap; + EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_ALLOCATE_BUFFER AllocateBuffer; + EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_FREE_BUFFER FreeBuffer; + EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_FLUSH Flush; + EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_GET_ATTRIBUTES GetAttributes; + EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_SET_ATTRIBUTES SetAttributes; + EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_CONFIGURATION Configuration; + UINT32 SegmentNumber; +} EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL; + +#endif /* _EFI_PCI_IO_H */ diff --git a/gnu-efi/inc/efipoint.h b/gnu-efi/inc/efipoint.h new file mode 100644 index 0000000..4dbcf18 --- /dev/null +++ b/gnu-efi/inc/efipoint.h @@ -0,0 +1,115 @@ +/* Copyright (C) 2014 by John Cronin + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef _EFI_POINT_H +#define _EFI_POINT_H + +#define EFI_SIMPLE_POINTER_PROTOCOL_GUID \ + { 0x31878c87, 0xb75, 0x11d5, { 0x9a, 0x4f, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d } } + +INTERFACE_DECL(_EFI_SIMPLE_POINTER); + +typedef struct { + INT32 RelativeMovementX; + INT32 RelativeMovementY; + INT32 RelativeMovementZ; + BOOLEAN LeftButton; + BOOLEAN RightButton; +} EFI_SIMPLE_POINTER_STATE; + +typedef struct { + UINT64 ResolutionX; + UINT64 ResolutionY; + UINT64 ResolutionZ; + BOOLEAN LeftButton; + BOOLEAN RightButton; +} EFI_SIMPLE_POINTER_MODE; + +typedef +EFI_STATUS +(EFIAPI *EFI_SIMPLE_POINTER_RESET) ( + IN struct _EFI_SIMPLE_POINTER *This, + IN BOOLEAN ExtendedVerification +); + +typedef +EFI_STATUS +(EFIAPI *EFI_SIMPLE_POINTER_GET_STATE) ( + IN struct _EFI_SIMPLE_POINTER *This, + IN OUT EFI_SIMPLE_POINTER_STATE *State +); + +typedef struct _EFI_SIMPLE_POINTER { + EFI_SIMPLE_POINTER_RESET Reset; + EFI_SIMPLE_POINTER_GET_STATE GetState; + EFI_EVENT WaitForInput; + EFI_SIMPLE_POINTER_MODE *Mode; +} EFI_SIMPLE_POINTER_PROTOCOL; + +#define EFI_ABSOLUTE_POINTER_PROTOCOL_GUID \ + { 0x8D59D32B, 0xC655, 0x4AE9, { 0x9B, 0x15, 0xF2, 0x59, 0x04, 0x99, 0x2A, 0x43 } } + +INTERFACE_DECL(_EFI_ABSOLUTE_POINTER_PROTOCOL); + +typedef struct { + UINT64 AbsoluteMinX; + UINT64 AbsoluteMinY; + UINT64 AbsoluteMinZ; + UINT64 AbsoluteMaxX; + UINT64 AbsoluteMaxY; + UINT64 AbsoluteMaxZ; + UINT32 Attributes; +} EFI_ABSOLUTE_POINTER_MODE; + +typedef struct { + UINT64 CurrentX; + UINT64 CurrentY; + UINT64 CurrentZ; + UINT32 ActiveButtons; +} EFI_ABSOLUTE_POINTER_STATE; + +#define EFI_ABSP_SupportsAltActive 0x00000001 +#define EFI_ABSP_SupportsPressureAsZ 0x00000002 +#define EFI_ABSP_TouchActive 0x00000001 +#define EFI_ABS_AltActive 0x00000002 + +typedef +EFI_STATUS +(EFIAPI *EFI_ABSOLUTE_POINTER_RESET) ( + IN struct _EFI_ABSOLUTE_POINTER_PROTOCOL *This, + IN BOOLEAN ExtendedVerification +); + +typedef +EFI_STATUS +(EFIAPI *EFI_ABSOLUTE_POINTER_GET_STATE) ( + IN struct _EFI_ABSOLUTE_POINTER_PROTOCOL *This, + IN OUT EFI_ABSOLUTE_POINTER_STATE *State +); + +typedef struct _EFI_ABSOLUTE_POINTER_PROTOCOL { + EFI_ABSOLUTE_POINTER_RESET Reset; + EFI_ABSOLUTE_POINTER_GET_STATE GetState; + EFI_EVENT WaitForInput; + EFI_ABSOLUTE_POINTER_MODE *Mode; +} EFI_ABSOLUTE_POINTER_PROTOCOL; + +#endif diff --git a/gnu-efi/inc/efiprot.h b/gnu-efi/inc/efiprot.h new file mode 100644 index 0000000..53fc560 --- /dev/null +++ b/gnu-efi/inc/efiprot.h @@ -0,0 +1,1424 @@ +#ifndef _EFI_PROT_H +#define _EFI_PROT_H + +/*++ + +Copyright (c) 1998 Intel Corporation + +Module Name: + + efiprot.h + +Abstract: + + EFI Protocols + + + +Revision History + +--*/ + +// +// FPSWA library protocol +// +#define EFI_FPSWA_PROTOCOL_GUID \ + { 0xc41b6531, 0x97b9, 0x11d3, {0x9a, 0x29, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d} } +#define FPSWA_PROTOCOL EFI_FPSWA_PROTOCOL_GUID + +// +// Device Path protocol +// + +#define EFI_DEVICE_PATH_PROTOCOL_GUID \ + { 0x9576e91, 0x6d3f, 0x11d2, {0x8e, 0x39, 0x0, 0xa0, 0xc9, 0x69, 0x72, 0x3b} } +#define DEVICE_PATH_PROTOCOL EFI_DEVICE_PATH_PROTOCOL_GUID + + +// +// Block IO protocol +// + +#define EFI_BLOCK_IO_PROTOCOL_GUID \ + { 0x964e5b21, 0x6459, 0x11d2, {0x8e, 0x39, 0x0, 0xa0, 0xc9, 0x69, 0x72, 0x3b} } +#define BLOCK_IO_PROTOCOL EFI_BLOCK_IO_PROTOCOL_GUID + +#define EFI_BLOCK_IO_PROTOCOL_REVISION 0x00010000 +#define EFI_BLOCK_IO_PROTOCOL_REVISION2 0x00020001 +#define EFI_BLOCK_IO_PROTOCOL_REVISION3 ((2<<16) | 31) +#define EFI_BLOCK_IO_INTERFACE_REVISION EFI_BLOCK_IO_PROTOCOL_REVISION +#define EFI_BLOCK_IO_INTERFACE_REVISION2 EFI_BLOCK_IO_PROTOCOL_REVISION2 +#define EFI_BLOCK_IO_INTERFACE_REVISION3 EFI_BLOCK_IO_PROTOCOL_REVISION3 + +INTERFACE_DECL(_EFI_BLOCK_IO_PROTOCOL); + +typedef +EFI_STATUS +(EFIAPI *EFI_BLOCK_RESET) ( + IN struct _EFI_BLOCK_IO_PROTOCOL *This, + IN BOOLEAN ExtendedVerification + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_BLOCK_READ) ( + IN struct _EFI_BLOCK_IO_PROTOCOL *This, + IN UINT32 MediaId, + IN EFI_LBA LBA, + IN UINTN BufferSize, + OUT VOID *Buffer + ); + + +typedef +EFI_STATUS +(EFIAPI *EFI_BLOCK_WRITE) ( + IN struct _EFI_BLOCK_IO_PROTOCOL *This, + IN UINT32 MediaId, + IN EFI_LBA LBA, + IN UINTN BufferSize, + IN VOID *Buffer + ); + + +typedef +EFI_STATUS +(EFIAPI *EFI_BLOCK_FLUSH) ( + IN struct _EFI_BLOCK_IO_PROTOCOL *This + ); + + + +typedef struct { + UINT32 MediaId; + BOOLEAN RemovableMedia; + BOOLEAN MediaPresent; + + BOOLEAN LogicalPartition; + BOOLEAN ReadOnly; + BOOLEAN WriteCaching; + + UINT32 BlockSize; + UINT32 IoAlign; + + EFI_LBA LastBlock; + + /* revision 2 */ + EFI_LBA LowestAlignedLba; + UINT32 LogicalBlocksPerPhysicalBlock; + /* revision 3 */ + UINT32 OptimalTransferLengthGranularity; +} EFI_BLOCK_IO_MEDIA; + +typedef struct _EFI_BLOCK_IO_PROTOCOL { + UINT64 Revision; + + EFI_BLOCK_IO_MEDIA *Media; + + EFI_BLOCK_RESET Reset; + EFI_BLOCK_READ ReadBlocks; + EFI_BLOCK_WRITE WriteBlocks; + EFI_BLOCK_FLUSH FlushBlocks; + +} EFI_BLOCK_IO_PROTOCOL; + +typedef struct _EFI_BLOCK_IO_PROTOCOL _EFI_BLOCK_IO; +typedef EFI_BLOCK_IO_PROTOCOL EFI_BLOCK_IO; + +#define EFI_BLOCK_IO2_PROTOCOL_GUID \ + { 0xa77b2472, 0xe282, 0x4e9f, {0xa2, 0x45, 0xc2, 0xc0, 0xe2, 0x7b, 0xbc, 0xc1} } + +INTERFACE_DECL(_EFI_BLOCK_IO2_PROTOCOL); + +typedef struct { + EFI_EVENT Event; + EFI_STATUS TransactionStatus; +} EFI_BLOCK_IO2_TOKEN; + +typedef +EFI_STATUS +(EFIAPI *EFI_BLOCK_RESET_EX) ( + IN struct _EFI_BLOCK_IO2_PROTOCOL *This, + IN BOOLEAN ExtendedVerification + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_BLOCK_READ_EX) ( + IN struct _EFI_BLOCK_IO2_PROTOCOL *This, + IN UINT32 MediaId, + IN EFI_LBA LBA, + IN OUT EFI_BLOCK_IO2_TOKEN *Token, + IN UINTN BufferSize, + OUT VOID *Buffer + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_BLOCK_WRITE_EX) ( + IN struct _EFI_BLOCK_IO2_PROTOCOL *This, + IN UINT32 MediaId, + IN EFI_LBA LBA, + IN OUT EFI_BLOCK_IO2_TOKEN *Token, + IN UINTN BufferSize, + IN VOID *Buffer + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_BLOCK_FLUSH_EX) ( + IN struct _EFI_BLOCK_IO2_PROTOCOL *This, + IN OUT EFI_BLOCK_IO2_TOKEN *Token + ); + +typedef struct _EFI_BLOCK_IO2_PROTOCOL { + EFI_BLOCK_IO_MEDIA *Media; + EFI_BLOCK_RESET_EX Reset; + EFI_BLOCK_READ_EX ReadBlocksEx; + EFI_BLOCK_WRITE_EX WriteBlocksEx; + EFI_BLOCK_FLUSH_EX FlushBlocksEx; +} EFI_BLOCK_IO2_PROTOCOL; + +// +// Disk Block IO protocol +// + +#define EFI_DISK_IO_PROTOCOL_GUID \ + { 0xce345171, 0xba0b, 0x11d2, {0x8e, 0x4f, 0x0, 0xa0, 0xc9, 0x69, 0x72, 0x3b} } +#define DISK_IO_PROTOCOL EFI_DISK_IO_PROTOCOL_GUID + +#define EFI_DISK_IO_PROTOCOL_REVISION 0x00010000 +#define EFI_DISK_IO_INTERFACE_REVISION EFI_DISK_IO_PROTOCOL_REVISION + +INTERFACE_DECL(_EFI_DISK_IO_PROTOCOL); + +typedef +EFI_STATUS +(EFIAPI *EFI_DISK_READ) ( + IN struct _EFI_DISK_IO_PROTOCOL *This, + IN UINT32 MediaId, + IN UINT64 Offset, + IN UINTN BufferSize, + OUT VOID *Buffer + ); + + +typedef +EFI_STATUS +(EFIAPI *EFI_DISK_WRITE) ( + IN struct _EFI_DISK_IO_PROTOCOL *This, + IN UINT32 MediaId, + IN UINT64 Offset, + IN UINTN BufferSize, + IN VOID *Buffer + ); + + +typedef struct _EFI_DISK_IO_PROTOCOL { + UINT64 Revision; + EFI_DISK_READ ReadDisk; + EFI_DISK_WRITE WriteDisk; +} EFI_DISK_IO_PROTOCOL; + +typedef struct _EFI_DISK_IO_PROTOCOL _EFI_DISK_IO; +typedef EFI_DISK_IO_PROTOCOL EFI_DISK_IO; + + +#define EFI_DISK_IO2_PROTOCOL_GUID \ + { 0x151c8eae, 0x7f2c, 0x472c, {0x9e, 0x54, 0x98, 0x28, 0x19, 0x4f, 0x6a, 0x88} } + +#define EFI_DISK_IO2_PROTOCOL_REVISION 0x00020000 + +INTERFACE_DECL(_EFI_DISK_IO2_PROTOCOL); + +typedef struct { + EFI_EVENT Event; + EFI_STATUS TransactionStatus; +} EFI_DISK_IO2_TOKEN; + +typedef +EFI_STATUS +(EFIAPI *EFI_DISK_CANCEL_EX) ( + IN struct _EFI_DISK_IO2_PROTOCOL *This + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_DISK_READ_EX) ( + IN struct _EFI_DISK_IO2_PROTOCOL *This, + IN UINT32 MediaId, + IN UINT64 Offset, + IN OUT EFI_DISK_IO2_TOKEN *Token, + IN UINTN BufferSize, + OUT VOID *Buffer + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_DISK_WRITE_EX) ( + IN struct _EFI_DISK_IO2_PROTOCOL *This, + IN UINT32 MediaId, + IN UINT64 Offset, + IN OUT EFI_DISK_IO2_TOKEN *Token, + IN UINTN BufferSize, + IN VOID *Buffer + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_DISK_FLUSH_EX) ( + IN struct _EFI_DISK_IO2_PROTOCOL *This, + IN OUT EFI_DISK_IO2_TOKEN *Token + ); + +typedef struct _EFI_DISK_IO2_PROTOCOL { + UINT64 Revision; + EFI_DISK_CANCEL_EX Cancel; + EFI_DISK_READ_EX ReadDiskEx; + EFI_DISK_WRITE_EX WriteDiskEx; + EFI_DISK_FLUSH_EX FlushDiskEx; +} EFI_DISK_IO2_PROTOCOL; + +// +// Simple file system protocol +// + +#define EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID \ + { 0x964e5b22, 0x6459, 0x11d2, {0x8e, 0x39, 0x0, 0xa0, 0xc9, 0x69, 0x72, 0x3b} } +#define SIMPLE_FILE_SYSTEM_PROTOCOL EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID + +INTERFACE_DECL(_EFI_SIMPLE_FILE_SYSTEM_PROTOCOL); +INTERFACE_DECL(_EFI_FILE_HANDLE); + +typedef +EFI_STATUS +(EFIAPI *EFI_VOLUME_OPEN) ( + IN struct _EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *This, + OUT struct _EFI_FILE_HANDLE **Root + ); + +#define EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_REVISION 0x00010000 +#define EFI_FILE_IO_INTERFACE_REVISION EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_REVISION + +typedef struct _EFI_SIMPLE_FILE_SYSTEM_PROTOCOL { + UINT64 Revision; + EFI_VOLUME_OPEN OpenVolume; +} EFI_SIMPLE_FILE_SYSTEM_PROTOCOL; + +typedef struct _EFI_SIMPLE_FILE_SYSTEM_PROTOCOL _EFI_FILE_IO_INTERFACE; +typedef EFI_SIMPLE_FILE_SYSTEM_PROTOCOL EFI_FILE_IO_INTERFACE; + +// +// +// + +typedef +EFI_STATUS +(EFIAPI *EFI_FILE_OPEN) ( + IN struct _EFI_FILE_HANDLE *File, + OUT struct _EFI_FILE_HANDLE **NewHandle, + IN CHAR16 *FileName, + IN UINT64 OpenMode, + IN UINT64 Attributes + ); + +// Open modes +#define EFI_FILE_MODE_READ 0x0000000000000001 +#define EFI_FILE_MODE_WRITE 0x0000000000000002 +#define EFI_FILE_MODE_CREATE 0x8000000000000000 + +// File attributes +#define EFI_FILE_READ_ONLY 0x0000000000000001 +#define EFI_FILE_HIDDEN 0x0000000000000002 +#define EFI_FILE_SYSTEM 0x0000000000000004 +#define EFI_FILE_RESERVIED 0x0000000000000008 +#define EFI_FILE_DIRECTORY 0x0000000000000010 +#define EFI_FILE_ARCHIVE 0x0000000000000020 +#define EFI_FILE_VALID_ATTR 0x0000000000000037 + +typedef +EFI_STATUS +(EFIAPI *EFI_FILE_CLOSE) ( + IN struct _EFI_FILE_HANDLE *File + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_FILE_DELETE) ( + IN struct _EFI_FILE_HANDLE *File + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_FILE_READ) ( + IN struct _EFI_FILE_HANDLE *File, + IN OUT UINTN *BufferSize, + OUT VOID *Buffer + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_FILE_WRITE) ( + IN struct _EFI_FILE_HANDLE *File, + IN OUT UINTN *BufferSize, + IN VOID *Buffer + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_FILE_SET_POSITION) ( + IN struct _EFI_FILE_HANDLE *File, + IN UINT64 Position + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_FILE_GET_POSITION) ( + IN struct _EFI_FILE_HANDLE *File, + OUT UINT64 *Position + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_FILE_GET_INFO) ( + IN struct _EFI_FILE_HANDLE *File, + IN EFI_GUID *InformationType, + IN OUT UINTN *BufferSize, + OUT VOID *Buffer + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_FILE_SET_INFO) ( + IN struct _EFI_FILE_HANDLE *File, + IN EFI_GUID *InformationType, + IN UINTN BufferSize, + IN VOID *Buffer + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_FILE_FLUSH) ( + IN struct _EFI_FILE_HANDLE *File + ); + +typedef struct { + EFI_EVENT Event; + EFI_STATUS Status; + UINTN BufferSize; + VOID *Buffer; +} EFI_FILE_IO_TOKEN; + +typedef +EFI_STATUS +(EFIAPI *EFI_FILE_OPEN_EX)( + IN struct _EFI_FILE_HANDLE *File, + OUT struct _EFI_FILE_HANDLE **NewHandle, + IN CHAR16 *FileName, + IN UINT64 OpenMode, + IN UINT64 Attributes, + IN OUT EFI_FILE_IO_TOKEN *Token + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_FILE_READ_EX) ( + IN struct _EFI_FILE_HANDLE *File, + IN OUT EFI_FILE_IO_TOKEN *Token + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_FILE_WRITE_EX) ( + IN struct _EFI_FILE_HANDLE *File, + IN OUT EFI_FILE_IO_TOKEN *Token + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_FILE_FLUSH_EX) ( + IN struct _EFI_FILE_HANDLE *File, + IN OUT EFI_FILE_IO_TOKEN *Token + ); + +#define EFI_FILE_PROTOCOL_REVISION 0x00010000 +#define EFI_FILE_PROTOCOL_REVISION2 0x00020000 +#define EFI_FILE_PROTOCOL_LATEST_REVISION EFI_FILE_PROTOCOL_REVISION2 +#define EFI_FILE_HANDLE_REVISION EFI_FILE_PROTOCOL_REVISION + +typedef struct _EFI_FILE_HANDLE { + UINT64 Revision; + EFI_FILE_OPEN Open; + EFI_FILE_CLOSE Close; + EFI_FILE_DELETE Delete; + EFI_FILE_READ Read; + EFI_FILE_WRITE Write; + EFI_FILE_GET_POSITION GetPosition; + EFI_FILE_SET_POSITION SetPosition; + EFI_FILE_GET_INFO GetInfo; + EFI_FILE_SET_INFO SetInfo; + EFI_FILE_FLUSH Flush; + EFI_FILE_OPEN_EX OpenEx; + EFI_FILE_READ_EX ReadEx; + EFI_FILE_WRITE_EX WriteEx; + EFI_FILE_FLUSH_EX FlushEx; +} EFI_FILE_PROTOCOL, *EFI_FILE_HANDLE; + +typedef EFI_FILE_PROTOCOL EFI_FILE; + + +// +// File information types +// + +#define EFI_FILE_INFO_ID \ + { 0x9576e92, 0x6d3f, 0x11d2, {0x8e, 0x39, 0x0, 0xa0, 0xc9, 0x69, 0x72, 0x3b} } + +typedef struct { + UINT64 Size; + UINT64 FileSize; + UINT64 PhysicalSize; + EFI_TIME CreateTime; + EFI_TIME LastAccessTime; + EFI_TIME ModificationTime; + UINT64 Attribute; + CHAR16 FileName[1]; +} EFI_FILE_INFO; + +// +// The FileName field of the EFI_FILE_INFO data structure is variable length. +// Whenever code needs to know the size of the EFI_FILE_INFO data structure, it needs to +// be the size of the data structure without the FileName field. The following macro +// computes this size correctly no matter how big the FileName array is declared. +// This is required to make the EFI_FILE_INFO data structure ANSI compilant. +// + +#define SIZE_OF_EFI_FILE_INFO EFI_FIELD_OFFSET(EFI_FILE_INFO,FileName) + +#define EFI_FILE_SYSTEM_INFO_ID \ + { 0x9576e93, 0x6d3f, 0x11d2, {0x8e, 0x39, 0x0, 0xa0, 0xc9, 0x69, 0x72, 0x3b} } + +typedef struct { + UINT64 Size; + BOOLEAN ReadOnly; + UINT64 VolumeSize; + UINT64 FreeSpace; + UINT32 BlockSize; + CHAR16 VolumeLabel[1]; +} EFI_FILE_SYSTEM_INFO; + +// +// The VolumeLabel field of the EFI_FILE_SYSTEM_INFO data structure is variable length. +// Whenever code needs to know the size of the EFI_FILE_SYSTEM_INFO data structure, it needs +// to be the size of the data structure without the VolumeLable field. The following macro +// computes this size correctly no matter how big the VolumeLable array is declared. +// This is required to make the EFI_FILE_SYSTEM_INFO data structure ANSI compilant. +// + +#define SIZE_OF_EFI_FILE_SYSTEM_INFO EFI_FIELD_OFFSET(EFI_FILE_SYSTEM_INFO,VolumeLabel) + +#define EFI_FILE_SYSTEM_VOLUME_LABEL_INFO_ID \ + { 0xDB47D7D3,0xFE81, 0x11d3, {0x9A, 0x35, 0x00, 0x90, 0x27, 0x3F, 0xC1, 0x4D} } + +typedef struct { + CHAR16 VolumeLabel[1]; +} EFI_FILE_SYSTEM_VOLUME_LABEL_INFO; + +#define SIZE_OF_EFI_FILE_SYSTEM_VOLUME_LABEL_INFO EFI_FIELD_OFFSET(EFI_FILE_SYSTEM_VOLUME_LABEL_INFO,VolumeLabel) + +// +// Load file protocol +// + + +#define EFI_LOAD_FILE_PROTOCOL_GUID \ + { 0x56EC3091, 0x954C, 0x11d2, {0x8E, 0x3F, 0x00, 0xA0, 0xC9, 0x69, 0x72, 0x3B} } +#define LOAD_FILE_PROTOCOL EFI_LOAD_FILE_PROTOCOL_GUID + +INTERFACE_DECL(_EFI_LOAD_FILE_PROTOCOL); + +typedef +EFI_STATUS +(EFIAPI *EFI_LOAD_FILE) ( + IN struct _EFI_LOAD_FILE_PROTOCOL *This, + IN EFI_DEVICE_PATH *FilePath, + IN BOOLEAN BootPolicy, + IN OUT UINTN *BufferSize, + IN VOID *Buffer OPTIONAL + ); + +typedef struct _EFI_LOAD_FILE_PROTOCOL { + EFI_LOAD_FILE LoadFile; +} EFI_LOAD_FILE_PROTOCOL; + +typedef struct _EFI_LOAD_FILE_PROTOCOL _EFI_LOAD_FILE_INTERFACE; +typedef EFI_LOAD_FILE_PROTOCOL EFI_LOAD_FILE_INTERFACE; + +// +// Device IO protocol +// + +#define EFI_DEVICE_IO_PROTOCOL_GUID \ + { 0xaf6ac311, 0x84c3, 0x11d2, {0x8e, 0x3c, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b} } +#define DEVICE_IO_PROTOCOL EFI_DEVICE_IO_PROTOCOL_GUID + +INTERFACE_DECL(_EFI_DEVICE_IO_PROTOCOL); + +typedef enum { + IO_UINT8, + IO_UINT16, + IO_UINT32, + IO_UINT64, +// +// Specification Change: Copy from MMIO to MMIO vs. MMIO to buffer, buffer to MMIO +// + MMIO_COPY_UINT8, + MMIO_COPY_UINT16, + MMIO_COPY_UINT32, + MMIO_COPY_UINT64 +} EFI_IO_WIDTH; + +#define EFI_PCI_ADDRESS(_bus,_dev,_func) \ + ( (UINT64) ( (((UINTN)_bus) << 24) + (((UINTN)_dev) << 16) + (((UINTN)_func) << 8) ) ) + + +typedef +EFI_STATUS +(EFIAPI *EFI_DEVICE_IO) ( + IN struct _EFI_DEVICE_IO_PROTOCOL *This, + IN EFI_IO_WIDTH Width, + IN UINT64 Address, + IN UINTN Count, + IN OUT VOID *Buffer + ); + +typedef struct { + EFI_DEVICE_IO Read; + EFI_DEVICE_IO Write; +} EFI_IO_ACCESS; + +typedef +EFI_STATUS +(EFIAPI *EFI_PCI_DEVICE_PATH) ( + IN struct _EFI_DEVICE_IO_PROTOCOL *This, + IN UINT64 Address, + IN OUT EFI_DEVICE_PATH **PciDevicePath + ); + +typedef enum { + EfiBusMasterRead, + EfiBusMasterWrite, + EfiBusMasterCommonBuffer +} EFI_IO_OPERATION_TYPE; + +typedef +EFI_STATUS +(EFIAPI *EFI_IO_MAP) ( + IN struct _EFI_DEVICE_IO_PROTOCOL *This, + IN EFI_IO_OPERATION_TYPE Operation, + IN EFI_PHYSICAL_ADDRESS *HostAddress, + IN OUT UINTN *NumberOfBytes, + OUT EFI_PHYSICAL_ADDRESS *DeviceAddress, + OUT VOID **Mapping + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_IO_UNMAP) ( + IN struct _EFI_DEVICE_IO_PROTOCOL *This, + IN VOID *Mapping + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_IO_ALLOCATE_BUFFER) ( + IN struct _EFI_DEVICE_IO_PROTOCOL *This, + IN EFI_ALLOCATE_TYPE Type, + IN EFI_MEMORY_TYPE MemoryType, + IN UINTN Pages, + IN OUT EFI_PHYSICAL_ADDRESS *HostAddress + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_IO_FLUSH) ( + IN struct _EFI_DEVICE_IO_PROTOCOL *This + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_IO_FREE_BUFFER) ( + IN struct _EFI_DEVICE_IO_PROTOCOL *This, + IN UINTN Pages, + IN EFI_PHYSICAL_ADDRESS HostAddress + ); + +typedef struct _EFI_DEVICE_IO_PROTOCOL { + EFI_IO_ACCESS Mem; + EFI_IO_ACCESS Io; + EFI_IO_ACCESS Pci; + EFI_IO_MAP Map; + EFI_PCI_DEVICE_PATH PciDevicePath; + EFI_IO_UNMAP Unmap; + EFI_IO_ALLOCATE_BUFFER AllocateBuffer; + EFI_IO_FLUSH Flush; + EFI_IO_FREE_BUFFER FreeBuffer; +} EFI_DEVICE_IO_PROTOCOL; + +typedef struct _EFI_DEVICE_IO_PROTOCOL _EFI_DEVICE_IO_INTERFACE; +typedef EFI_DEVICE_IO_PROTOCOL EFI_DEVICE_IO_INTERFACE; + +// +// Unicode Collation protocol +// + +#define EFI_UNICODE_COLLATION_PROTOCOL_GUID \ + { 0x1d85cd7f, 0xf43d, 0x11d2, {0x9a, 0xc, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d} } +#define UNICODE_COLLATION_PROTOCOL EFI_UNICODE_COLLATION_PROTOCOL_GUID + +#define EFI_UNICODE_BYTE_ORDER_MARK (CHAR16)(0xfeff) +#define UNICODE_BYTE_ORDER_MARK EFI_UNICODE_BYTE_ORDER_MARK + +INTERFACE_DECL(_EFI_UNICODE_COLLATION_PROTOCOL); + +typedef +INTN +(EFIAPI *EFI_UNICODE_STRICOLL) ( + IN struct _EFI_UNICODE_COLLATION_PROTOCOL *This, + IN CHAR16 *s1, + IN CHAR16 *s2 + ); + +typedef +BOOLEAN +(EFIAPI *EFI_UNICODE_METAIMATCH) ( + IN struct _EFI_UNICODE_COLLATION_PROTOCOL *This, + IN CHAR16 *String, + IN CHAR16 *Pattern + ); + +typedef +VOID +(EFIAPI *EFI_UNICODE_STRLWR) ( + IN struct _EFI_UNICODE_COLLATION_PROTOCOL *This, + IN OUT CHAR16 *Str + ); + +typedef +VOID +(EFIAPI *EFI_UNICODE_STRUPR) ( + IN struct _EFI_UNICODE_COLLATION_PROTOCOL *This, + IN OUT CHAR16 *Str + ); + +typedef +VOID +(EFIAPI *EFI_UNICODE_FATTOSTR) ( + IN struct _EFI_UNICODE_COLLATION_PROTOCOL *This, + IN UINTN FatSize, + IN CHAR8 *Fat, + OUT CHAR16 *String + ); + +typedef +BOOLEAN +(EFIAPI *EFI_UNICODE_STRTOFAT) ( + IN struct _EFI_UNICODE_COLLATION_PROTOCOL *This, + IN CHAR16 *String, + IN UINTN FatSize, + OUT CHAR8 *Fat + ); + +// +// Hash Protocol +// +#define EFI_HASH_PROTOCOL_GUID \ + { 0xC5184932, 0xDBA5, 0x46DB, { 0xA5, 0xBA, 0xCC, 0x0B, 0xDA, 0x9C, 0x14, 0x35 } } +#define HASH_PROTOCOL EFI_HASH_PROTOCOL_GUID + +#define EFI_HASH_ALGORITHM_SHA1_GUID \ + { 0x2AE9D80F, 0x3FB2, 0x4095, { 0xB7, 0xB1, 0xE9, 0x31, 0x57, 0xB9, 0x46, 0xB6 } } // Deprecated +#define EFI_HASH_ALGORITHM_SHA1 EFI_HASH_ALGORITHM_SHA1_GUID + +#define EFI_HASH_ALGORITHM_SHA224_GUID \ + { 0x8DF01A06, 0x9BD5, 0x4BF7, { 0xB0, 0x21, 0xDB, 0x4F, 0xD9, 0xCC, 0xF4, 0x5B } } // Deprecated +#define EFI_HASH_ALGORITHM_SHA224 EFI_HASH_ALGORITHM_SHA224_GUID + +#define EFI_HASH_ALGORITHM_SHA256_GUID \ + { 0x51AA59DE, 0xFDF2, 0x4EA3, { 0xBC, 0x63, 0x87, 0x5F, 0xB7, 0x84, 0x2E, 0xE9 } } // Deprecated +#define EFI_HASH_ALGORITHM_SHA256 EFI_HASH_ALGORITHM_SHA256_GUID + +#define EFI_HASH_ALGORITHM_SHA384_GUID \ + { 0xEFA96432, 0xDE33, 0x4DD2, { 0xAE, 0xE6, 0x32, 0x8C, 0x33, 0xDF, 0x77, 0x7A } } // Deprecated +#define EFI_HASH_ALGORITHM_SHA384 EFI_HASH_ALGORITHM_SHA384_GUID + +#define EFI_HASH_ALGORITHM_SHA512_GUID \ + { 0xCAA4381E, 0x750C, 0x4770, { 0xB8, 0x70, 0x7A, 0x23, 0xB4, 0xE4, 0x21, 0x30 } } // Deprecated +#define EFI_HASH_ALGORITHM_SHA512 EFI_HASH_ALGORITHM_SHA512_GUID + +#define EFI_HASH_ALGORITHM_MD5_GUID \ + { 0x0AF7C79C, 0x65B5, 0x4319, { 0xB0, 0xAE, 0x44, 0xEC, 0x48, 0x4E, 0x4A, 0xD7 } } // Deprecated +#define EFI_HASH_ALGORITHM_MD5 EFI_HASH_ALGORITHM_MD5_GUID + +#define EFI_HASH_ALGORITHM_SHA1_NOPAD_GUID \ + { 0x24C5DC2F, 0x53E2, 0x40CA, { 0x9E, 0xD6, 0xA5, 0xD9, 0xA4, 0x9F, 0x46, 0x3B } } +#define EFI_HASH_ALGORITHM_SHA1_NOPAD EFI_HASH_ALGORITHM_SHA1_NOPAD_GUID + +#define EFI_HASH_ALGORITHM_SHA256_NOPAD_GUID \ + { 0x8628752A, 0x6CB7, 0x4814, { 0x96, 0xFC, 0x24, 0xA8, 0x15, 0xAC, 0x22, 0x26 } } +#define EFI_HASH_ALGORITHM_SHA256_NOPAD EFI_HASH_ALGORITHM_SHA256_NOPAD_GUID + + +INTERFACE_DECL(_EFI_HASH_PROTOCOL); + +typedef UINT8 EFI_MD5_HASH[16]; +typedef UINT8 EFI_SHA1_HASH[20]; +typedef UINT8 EFI_SHA224_HASH[28]; +typedef UINT8 EFI_SHA256_HASH[32]; +typedef UINT8 EFI_SHA384_HASH[48]; +typedef UINT8 EFI_SHA512_HASH[64]; +typedef union _EFI_HASH_OUTPUT { + EFI_MD5_HASH *Md5Hash; + EFI_SHA1_HASH *Sha1Hash; + EFI_SHA224_HASH *Sha224Hash; + EFI_SHA256_HASH *Sha256Hash; + EFI_SHA384_HASH *Sha384Hash; + EFI_SHA512_HASH *Sha512Hash; +} EFI_HASH_OUTPUT; + +typedef +EFI_STATUS +(EFIAPI *EFI_HASH_GET_HASH_SIZE) ( + IN CONST struct _EFI_HASH_PROTOCOL *This, + IN CONST EFI_GUID *HashAlgorithm, + OUT UINTN *HashSize); + +typedef +EFI_STATUS +(EFIAPI *EFI_HASH_HASH) ( + IN CONST struct _EFI_HASH_PROTOCOL *This, + IN CONST EFI_GUID *HashAlgorithm, + IN BOOLEAN Extend, + IN CONST UINT8 *Message, + IN UINT64 MessageSize, + IN OUT EFI_HASH_OUTPUT *Hash); + +typedef struct _EFI_HASH_PROTOCOL { + EFI_HASH_GET_HASH_SIZE GetHashSize; + EFI_HASH_HASH Hash; +} EFI_HASH_PROTOCOL; + +typedef struct _EFI_HASH_PROTOCOL _EFI_HASH; +typedef EFI_HASH_PROTOCOL EFI_HASH; + + +typedef struct _EFI_UNICODE_COLLATION_PROTOCOL { + + // general + EFI_UNICODE_STRICOLL StriColl; + EFI_UNICODE_METAIMATCH MetaiMatch; + EFI_UNICODE_STRLWR StrLwr; + EFI_UNICODE_STRUPR StrUpr; + + // for supporting fat volumes + EFI_UNICODE_FATTOSTR FatToStr; + EFI_UNICODE_STRTOFAT StrToFat; + + CHAR8 *SupportedLanguages; +} EFI_UNICODE_COLLATION_PROTOCOL; + +typedef EFI_UNICODE_COLLATION_PROTOCOL EFI_UNICODE_COLLATION_INTERFACE; + +/* Graphics output protocol */ +#define EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID \ + { 0x9042a9de, 0x23dc, 0x4a38, {0x96, 0xfb, 0x7a, 0xde, 0xd0, 0x80, 0x51, 0x6a } } +typedef struct _EFI_GRAPHICS_OUTPUT_PROTOCOL EFI_GRAPHICS_OUTPUT_PROTOCOL; + +typedef struct { + UINT32 RedMask; + UINT32 GreenMask; + UINT32 BlueMask; + UINT32 ReservedMask; +} EFI_PIXEL_BITMASK; + +typedef enum { + PixelRedGreenBlueReserved8BitPerColor, + PixelBlueGreenRedReserved8BitPerColor, + PixelBitMask, + PixelBltOnly, + PixelFormatMax +} EFI_GRAPHICS_PIXEL_FORMAT; + +typedef struct { + UINT32 Version; + UINT32 HorizontalResolution; + UINT32 VerticalResolution; + EFI_GRAPHICS_PIXEL_FORMAT PixelFormat; + EFI_PIXEL_BITMASK PixelInformation; + UINT32 PixelsPerScanLine; +} EFI_GRAPHICS_OUTPUT_MODE_INFORMATION; + +/** + Return the current video mode information. + + @param This Protocol instance pointer. + @param ModeNumber The mode number to return information on. + @param SizeOfInfo A pointer to the size, in bytes, of the Info buffer. + @param Info A pointer to callee allocated buffer that returns information about ModeNumber. + + @retval EFI_SUCCESS Mode information returned. + @retval EFI_BUFFER_TOO_SMALL The Info buffer was too small. + @retval EFI_DEVICE_ERROR A hardware error occurred trying to retrieve the video mode. + @retval EFI_NOT_STARTED Video display is not initialized. Call SetMode () + @retval EFI_INVALID_PARAMETER One of the input args was NULL. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_GRAPHICS_OUTPUT_PROTOCOL_QUERY_MODE) ( + IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This, + IN UINT32 ModeNumber, + OUT UINTN *SizeOfInfo, + OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION **Info + ) +; + +/** + Return the current video mode information. + + @param This Protocol instance pointer. + @param ModeNumber The mode number to be set. + + @retval EFI_SUCCESS Graphics mode was changed. + @retval EFI_DEVICE_ERROR The device had an error and could not complete the request. + @retval EFI_UNSUPPORTED ModeNumber is not supported by this device. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_GRAPHICS_OUTPUT_PROTOCOL_SET_MODE) ( + IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This, + IN UINT32 ModeNumber + ); + +typedef struct { + UINT8 Blue; + UINT8 Green; + UINT8 Red; + UINT8 Reserved; +} EFI_GRAPHICS_OUTPUT_BLT_PIXEL; + +typedef union { + EFI_GRAPHICS_OUTPUT_BLT_PIXEL Pixel; + UINT32 Raw; +} EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION; + +typedef enum { + EfiBltVideoFill, + EfiBltVideoToBltBuffer, + EfiBltBufferToVideo, + EfiBltVideoToVideo, + EfiGraphicsOutputBltOperationMax +} EFI_GRAPHICS_OUTPUT_BLT_OPERATION; + +/** + The following table defines actions for BltOperations: + + EfiBltVideoFill - Write data from the BltBuffer pixel (SourceX, SourceY) + directly to every pixel of the video display rectangle + (DestinationX, DestinationY) (DestinationX + Width, DestinationY + Height). + Only one pixel will be used from the BltBuffer. Delta is NOT used. + + EfiBltVideoToBltBuffer - Read data from the video display rectangle + (SourceX, SourceY) (SourceX + Width, SourceY + Height) and place it in + the BltBuffer rectangle (DestinationX, DestinationY ) + (DestinationX + Width, DestinationY + Height). If DestinationX or + DestinationY is not zero then Delta must be set to the length in bytes + of a row in the BltBuffer. + + EfiBltBufferToVideo - Write data from the BltBuffer rectangle + (SourceX, SourceY) (SourceX + Width, SourceY + Height) directly to the + video display rectangle (DestinationX, DestinationY) + (DestinationX + Width, DestinationY + Height). If SourceX or SourceY is + not zero then Delta must be set to the length in bytes of a row in the + BltBuffer. + + EfiBltVideoToVideo - Copy from the video display rectangle (SourceX, SourceY) + (SourceX + Width, SourceY + Height) .to the video display rectangle + (DestinationX, DestinationY) (DestinationX + Width, DestinationY + Height). + The BltBuffer and Delta are not used in this mode. + + @param This Protocol instance pointer. + @param BltBuffer Buffer containing data to blit into video buffer. This + buffer has a size of Width*Height*sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL) + @param BltOperation Operation to perform on BlitBuffer and video memory + @param SourceX X coordinate of source for the BltBuffer. + @param SourceY Y coordinate of source for the BltBuffer. + @param DestinationX X coordinate of destination for the BltBuffer. + @param DestinationY Y coordinate of destination for the BltBuffer. + @param Width Width of rectangle in BltBuffer in pixels. + @param Height Hight of rectangle in BltBuffer in pixels. + @param Delta OPTIONAL + + @retval EFI_SUCCESS The Blt operation completed. + @retval EFI_INVALID_PARAMETER BltOperation is not valid. + @retval EFI_DEVICE_ERROR A hardware error occured writting to the video buffer. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_GRAPHICS_OUTPUT_PROTOCOL_BLT) ( + IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This, + IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer, OPTIONAL + IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation, + IN UINTN SourceX, + IN UINTN SourceY, + IN UINTN DestinationX, + IN UINTN DestinationY, + IN UINTN Width, + IN UINTN Height, + IN UINTN Delta OPTIONAL + ); + +typedef struct { + UINT32 MaxMode; + UINT32 Mode; + EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Info; + UINTN SizeOfInfo; + EFI_PHYSICAL_ADDRESS FrameBufferBase; + UINTN FrameBufferSize; +} EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE; + +struct _EFI_GRAPHICS_OUTPUT_PROTOCOL { + EFI_GRAPHICS_OUTPUT_PROTOCOL_QUERY_MODE QueryMode; + EFI_GRAPHICS_OUTPUT_PROTOCOL_SET_MODE SetMode; + EFI_GRAPHICS_OUTPUT_PROTOCOL_BLT Blt; + EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE *Mode; +}; + + + +/* + * EFI EDID Discovered Protocol + * UEFI Specification Version 2.5 Section 11.9 + */ +#define EFI_EDID_DISCOVERED_PROTOCOL_GUID \ + { 0x1C0C34F6, 0xD380, 0x41FA, { 0xA0, 0x49, 0x8a, 0xD0, 0x6C, 0x1A, 0x66, 0xAA} } + +typedef struct _EFI_EDID_DISCOVERED_PROTOCOL { + UINT32 SizeOfEdid; + UINT8 *Edid; +} EFI_EDID_DISCOVERED_PROTOCOL; + + + +/* + * EFI EDID Active Protocol + * UEFI Specification Version 2.5 Section 11.9 + */ +#define EFI_EDID_ACTIVE_PROTOCOL_GUID \ + { 0xBD8C1056, 0x9F36, 0x44EC, { 0x92, 0xA8, 0xA6, 0x33, 0x7F, 0x81, 0x79, 0x86} } + +typedef struct _EFI_EDID_ACTIVE_PROTOCOL { + UINT32 SizeOfEdid; + UINT8 *Edid; +} EFI_EDID_ACTIVE_PROTOCOL; + + + +/* + * EFI EDID Override Protocol + * UEFI Specification Version 2.5 Section 11.9 + */ +#define EFI_EDID_OVERRIDE_PROTOCOL_GUID \ + { 0x48ECB431, 0xFB72, 0x45C0, { 0xA9, 0x22, 0xF4, 0x58, 0xFE, 0x04, 0x0B, 0xD5} } + +INTERFACE_DECL(_EFI_EDID_OVERRIDE_PROTOCOL); + +typedef +EFI_STATUS +(EFIAPI *EFI_EDID_OVERRIDE_PROTOCOL_GET_EDID) ( + IN struct _EFI_EDID_OVERRIDE_PROTOCOL *This, + IN EFI_HANDLE *ChildHandle, + OUT UINT32 *Attributes, + IN OUT UINTN *EdidSize, + IN OUT UINT8 **Edid); + +typedef struct _EFI_EDID_OVERRIDE_PROTOCOL { + EFI_EDID_OVERRIDE_PROTOCOL_GET_EDID GetEdid; +} EFI_EDID_OVERRIDE_PROTOCOL; + + + +INTERFACE_DECL(_EFI_SERVICE_BINDING); + +typedef +EFI_STATUS +(EFIAPI *EFI_SERVICE_BINDING_CREATE_CHILD) ( + IN struct _EFI_SERVICE_BINDING *This, + IN EFI_HANDLE *ChildHandle + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_SERVICE_BINDING_DESTROY_CHILD) ( + IN struct _EFI_SERVICE_BINDING *This, + IN EFI_HANDLE ChildHandle + ); + +typedef struct _EFI_SERVICE_BINDING { + EFI_SERVICE_BINDING_CREATE_CHILD CreateChild; + EFI_SERVICE_BINDING_DESTROY_CHILD DestroyChild; +} EFI_SERVICE_BINDING; + + + +/* + * EFI Driver Binding Protocol + * UEFI Specification Version 2.5 Section 10.1 + */ +#define EFI_DRIVER_BINDING_PROTOCOL_GUID \ + { 0x18A031AB, 0xB443, 0x4D1A, { 0xA5, 0xC0, 0x0C, 0x09, 0x26, 0x1E, 0x9F, 0x71} } +#define DRIVER_BINDING_PROTOCOL EFI_DRIVER_BINDING_PROTOCOL_GUID + +INTERFACE_DECL(_EFI_DRIVER_BINDING_PROTOCOL); + +typedef +EFI_STATUS +(EFIAPI *EFI_DRIVER_BINDING_PROTOCOL_SUPPORTED) ( + IN struct _EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_DEVICE_PATH *RemainingDevicePath OPTIONAL); + +typedef +EFI_STATUS +(EFIAPI *EFI_DRIVER_BINDING_PROTOCOL_START) ( + IN struct _EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_DEVICE_PATH *RemainingDevicePath OPTIONAL); + +typedef +EFI_STATUS +(EFIAPI *EFI_DRIVER_BINDING_PROTOCOL_STOP) ( + IN struct _EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer OPTIONAL); + +typedef struct _EFI_DRIVER_BINDING_PROTOCOL { + EFI_DRIVER_BINDING_PROTOCOL_SUPPORTED Supported; + EFI_DRIVER_BINDING_PROTOCOL_START Start; + EFI_DRIVER_BINDING_PROTOCOL_STOP Stop; + UINT32 Version; + EFI_HANDLE ImageHandle; + EFI_HANDLE DriverBindingHandle; +} EFI_DRIVER_BINDING_PROTOCOL; + +typedef struct _EFI_DRIVER_BINDING_PROTOCOL _EFI_DRIVER_BINDING; +typedef EFI_DRIVER_BINDING_PROTOCOL EFI_DRIVER_BINDING; + + +/* + * Backwards compatibility with older GNU-EFI versions. Deprecated. + */ +#define EFI_DRIVER_SUPPORTED EFI_DRIVER_BINDING_PROTOCOL_SUPPORTED +#define EFI_DRIVER_START EFI_DRIVER_BINDING_PROTOCOL_START +#define EFI_DRIVER_STOP EFI_DRIVER_BINDING_PROTOCOL_STOP + + + +/* + * EFI Component Name Protocol + * Deprecated - use EFI Component Name 2 Protocol instead + */ +#define EFI_COMPONENT_NAME_PROTOCOL_GUID \ + {0x107A772C, 0xD5E1, 0x11D4, { 0x9A, 0x46, 0x00, 0x90, 0x27, 0x3F, 0xC1, 0x4D} } +#define COMPONENT_NAME_PROTOCOL EFI_COMPONENT_NAME_PROTOCOL_GUID + +INTERFACE_DECL(_EFI_COMPONENT_NAME_PROTOCOL); + +typedef +EFI_STATUS +(EFIAPI *EFI_COMPONENT_NAME_GET_DRIVER_NAME) ( + IN struct _EFI_COMPONENT_NAME_PROTOCOL *This, + IN CHAR8 *Language, + OUT CHAR16 **DriverName); + +typedef +EFI_STATUS +(EFIAPI *EFI_COMPONENT_NAME_GET_CONTROLLER_NAME) ( + IN struct _EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName); + +typedef struct _EFI_COMPONENT_NAME_PROTOCOL { + EFI_COMPONENT_NAME_GET_DRIVER_NAME GetDriverName; + EFI_COMPONENT_NAME_GET_CONTROLLER_NAME GetControllerName; + CHAR8 *SupportedLanguages; +} EFI_COMPONENT_NAME_PROTOCOL; + +typedef struct _EFI_COMPONENT_NAME_PROTOCOL _EFI_COMPONENT_NAME; +typedef EFI_COMPONENT_NAME_PROTOCOL EFI_COMPONENT_NAME; + + +/* + * EFI Component Name 2 Protocol + * UEFI Specification Version 2.5 Section 10.5 + */ +#define EFI_COMPONENT_NAME2_PROTOCOL_GUID \ + {0x6A7A5CFF, 0xE8D9, 0x4F70, { 0xBA, 0xDA, 0x75, 0xAB, 0x30, 0x25, 0xCE, 0x14} } +#define COMPONENT_NAME2_PROTOCOL EFI_COMPONENT_NAME2_PROTOCOL_GUID + +INTERFACE_DECL(_EFI_COMPONENT_NAME2_PROTOCOL); + +typedef +EFI_STATUS +(EFIAPI *EFI_COMPONENT_NAME2_GET_DRIVER_NAME) ( + IN struct _EFI_COMPONENT_NAME2_PROTOCOL *This, + IN CHAR8 *Language, + OUT CHAR16 **DriverName); + +typedef +EFI_STATUS +(EFIAPI *EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) ( + IN struct _EFI_COMPONENT_NAME2_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName); + +typedef struct _EFI_COMPONENT_NAME2_PROTOCOL { + EFI_COMPONENT_NAME2_GET_DRIVER_NAME GetDriverName; + EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME GetControllerName; + CHAR8 *SupportedLanguages; +} EFI_COMPONENT_NAME2_PROTOCOL; + +typedef struct _EFI_COMPONENT_NAME2_PROTOCOL _EFI_COMPONENT_NAME2; +typedef EFI_COMPONENT_NAME2_PROTOCOL EFI_COMPONENT_NAME2; + + + +/* + * EFI Loaded Image Protocol + * UEFI Specification Version 2.5 Section 8.1 + */ +#define EFI_LOADED_IMAGE_PROTOCOL_GUID \ + { 0x5B1B31A1, 0x9562, 0x11d2, {0x8E, 0x3F, 0x00, 0xA0, 0xC9, 0x69, 0x72, 0x3B} } +#define LOADED_IMAGE_PROTOCOL EFI_LOADED_IMAGE_PROTOCOL_GUID + +#define EFI_LOADED_IMAGE_PROTOCOL_REVISION 0x1000 +#define EFI_IMAGE_INFORMATION_REVISION EFI_LOADED_IMAGE_PROTOCOL_REVISION + +typedef +EFI_STATUS +(EFIAPI *EFI_IMAGE_UNLOAD) ( + IN EFI_HANDLE ImageHandle + ); + +typedef struct { + UINT32 Revision; + EFI_HANDLE ParentHandle; + struct _EFI_SYSTEM_TABLE *SystemTable; + + // Source location of image + EFI_HANDLE DeviceHandle; + EFI_DEVICE_PATH *FilePath; + VOID *Reserved; + + // Images load options + UINT32 LoadOptionsSize; + VOID *LoadOptions; + + // Location of where image was loaded + VOID *ImageBase; + UINT64 ImageSize; + EFI_MEMORY_TYPE ImageCodeType; + EFI_MEMORY_TYPE ImageDataType; + + // If the driver image supports a dynamic unload request + EFI_IMAGE_UNLOAD Unload; +} EFI_LOADED_IMAGE_PROTOCOL; + +typedef EFI_LOADED_IMAGE_PROTOCOL EFI_LOADED_IMAGE; + + + +/* + * Random Number Generator Protocol + * UEFI Specification Version 2.5 Section 35.5 + */ +#define EFI_RNG_PROTOCOL_GUID \ + { 0x3152bca5, 0xeade, 0x433d, {0x86, 0x2e, 0xc0, 0x1c, 0xdc, 0x29, 0x1f, 0x44} } + +typedef EFI_GUID EFI_RNG_ALGORITHM; + +#define EFI_RNG_ALGORITHM_SP800_90_HASH_256_GUID \ + {0xa7af67cb, 0x603b, 0x4d42, {0xba, 0x21, 0x70, 0xbf, 0xb6, 0x29, 0x3f, 0x96} } + +#define EFI_RNG_ALGORITHM_SP800_90_HMAC_256_GUID \ + {0xc5149b43, 0xae85, 0x4f53, {0x99, 0x82, 0xb9, 0x43, 0x35, 0xd3, 0xa9, 0xe7} } + +#define EFI_RNG_ALGORITHM_SP800_90_CTR_256_GUID \ + {0x44f0de6e, 0x4d8c, 0x4045, {0xa8, 0xc7, 0x4d, 0xd1, 0x68, 0x85, 0x6b, 0x9e} } + +#define EFI_RNG_ALGORITHM_X9_31_3DES_GUID \ + {0x63c4785a, 0xca34, 0x4012, {0xa3, 0xc8, 0x0b, 0x6a, 0x32, 0x4f, 0x55, 0x46} } + +#define EFI_RNG_ALGORITHM_X9_31_AES_GUID \ + {0xacd03321, 0x777e, 0x4d3d, {0xb1, 0xc8, 0x20, 0xcf, 0xd8, 0x88, 0x20, 0xc9} } + +#define EFI_RNG_ALGORITHM_RAW \ + {0xe43176d7, 0xb6e8, 0x4827, {0xb7, 0x84, 0x7f, 0xfd, 0xc4, 0xb6, 0x85, 0x61} } + +INTERFACE_DECL(_EFI_RNG_PROTOCOL); + +typedef +EFI_STATUS +(EFIAPI *EFI_RNG_GET_INFO) ( + IN struct _EFI_RNG_PROTOCOL *This, + IN OUT UINTN *RNGAlgorithmListSize, + OUT EFI_RNG_ALGORITHM *RNGAlgorithmList +); + +typedef +EFI_STATUS +(EFIAPI *EFI_RNG_GET_RNG) ( + IN struct _EFI_RNG_PROTOCOL *This, + IN EFI_RNG_ALGORITHM *RNGAlgorithm, OPTIONAL + IN UINTN RNGValueLength, + OUT UINT8 *RNGValue +); + +typedef struct _EFI_RNG_PROTOCOL { + EFI_RNG_GET_INFO GetInfo; + EFI_RNG_GET_RNG GetRNG; +} EFI_RNG_PROTOCOL; + + +// +// EFI_PLATFORM_DRIVER_OVERRIDE_PROTOCOL +// + +#define EFI_PLATFORM_DRIVER_OVERRIDE_PROTOCOL_GUID \ + { 0x6b30c738, 0xa391, 0x11d4, {0x9a, 0x3b, 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d} } + +INTERFACE_DECL(_EFI_PLATFORM_DRIVER_OVERRIDE_PROTOCOL); + +typedef +EFI_STATUS +(EFIAPI *EFI_PLATFORM_DRIVER_OVERRIDE_GET_DRIVER) ( +IN struct _EFI_PLATFORM_DRIVER_OVERRIDE_PROTOCOL *This, +IN EFI_HANDLE ControllerHandle, +IN OUT EFI_HANDLE *DriverImageHandle); + +typedef +EFI_STATUS +(EFIAPI *EFI_PLATFORM_DRIVER_OVERRIDE_GET_DRIVER_PATH) ( +IN struct _EFI_PLATFORM_DRIVER_OVERRIDE_PROTOCOL *This, +IN EFI_HANDLE ControllerHandle, +IN OUT EFI_DEVICE_PATH **DriverImagePath); + +typedef +EFI_STATUS +(EFIAPI *EFI_PLATFORM_DRIVER_OVERRIDE_DRIVER_LOADED) ( +IN struct _EFI_PLATFORM_DRIVER_OVERRIDE_PROTOCOL *This, +IN EFI_HANDLE ControllerHandle, +IN EFI_DEVICE_PATH *DriverImagePath, +IN EFI_HANDLE DriverImageHandle); + +typedef struct _EFI_PLATFORM_DRIVER_OVERRIDE_PROTOCOL { + EFI_PLATFORM_DRIVER_OVERRIDE_GET_DRIVER GetDriver; + EFI_PLATFORM_DRIVER_OVERRIDE_GET_DRIVER_PATH GetDriverPath; + EFI_PLATFORM_DRIVER_OVERRIDE_DRIVER_LOADED DriverLoaded; +} EFI_PLATFORM_DRIVER_OVERRIDE_PROTOCOL; + +// +// EFI_BUS_SPECIFIC_DRIVER_OVERRIDE_PROTOCOL +// + +#define EFI_BUS_SPECIFIC_DRIVER_OVERRIDE_PROTOCOL_GUID \ + { 0x3bc1b285, 0x8a15, 0x4a82, {0xaa, 0xbf, 0x4d, 0x7d, 0x13, 0xfb, 0x32, 0x65} } + +INTERFACE_DECL(_EFI_BUS_SPECIFIC_DRIVER_OVERRIDE_PROTOCOL); + +typedef +EFI_STATUS +(EFIAPI *EFI_BUS_SPECIFIC_DRIVER_OVERRIDE_GET_DRIVER) ( +IN struct _EFI_BUS_SPECIFIC_DRIVER_OVERRIDE_PROTOCOL *This, +IN OUT EFI_HANDLE *DriverImageHandle); + +typedef struct _EFI_BUS_SPECIFIC_DRIVER_OVERRIDE_PROTOCOL { + EFI_BUS_SPECIFIC_DRIVER_OVERRIDE_GET_DRIVER GetDriver; +} EFI_BUS_SPECIFIC_DRIVER_OVERRIDE_PROTOCOL; + +// +// EFI_DRIVER_FAMILY_OVERRIDE_PROTOCOL +// + +#define EFI_DRIVER_FAMILY_OVERRIDE_PROTOCOL_GUID \ + { 0xb1ee129e, 0xda36, 0x4181, {0x91, 0xf8, 0x04, 0xa4, 0x92, 0x37, 0x66, 0xa7} } + +INTERFACE_DECL(_EFI_DRIVER_FAMILY_OVERRIDE_PROTOCOL); + +typedef +UINT32 +(EFIAPI *EFI_DRIVER_FAMILY_OVERRIDE_GET_VERSION) ( +IN struct _EFI_DRIVER_FAMILY_OVERRIDE_PROTOCOL *This); + +typedef struct _EFI_DRIVER_FAMILY_OVERRIDE_PROTOCOL { + EFI_DRIVER_FAMILY_OVERRIDE_GET_VERSION GetVersion; +} EFI_DRIVER_FAMILY_OVERRIDE_PROTOCOL; + +// +// EFI_EBC_PROTOCOL +// + +#define EFI_EBC_INTERPRETER_PROTOCOL_GUID \ + {0x13ac6dd1, 0x73d0, 0x11d4, {0xb0, 0x6b, 0x00, 0xaa, 0x00, 0xbd, 0x6d, 0xe7} } + +#define EFI_EBC_PROTOCOL_GUID EFI_EBC_INTERPRETER_PROTOCOL_GUID + +INTERFACE_DECL(_EFI_EBC_PROTOCOL); + +typedef +EFI_STATUS +(EFIAPI *EFI_EBC_CREATE_THUNK)( + IN struct _EFI_EBC_PROTOCOL *This, + IN EFI_HANDLE ImageHandle, + IN VOID *EbcEntryPoint, + OUT VOID **Thunk); + +typedef +EFI_STATUS +(EFIAPI *EFI_EBC_UNLOAD_IMAGE)( + IN struct _EFI_EBC_PROTOCOL *This, + IN EFI_HANDLE ImageHandle); + +typedef +EFI_STATUS +(EFIAPI *EBC_ICACHE_FLUSH)( + IN EFI_PHYSICAL_ADDRESS Start, + IN UINT64 Length); + +typedef +EFI_STATUS +(EFIAPI *EFI_EBC_REGISTER_ICACHE_FLUSH)( + IN struct _EFI_EBC_PROTOCOL *This, + IN EBC_ICACHE_FLUSH Flush); + +typedef +EFI_STATUS +(EFIAPI *EFI_EBC_GET_VERSION)( + IN struct _EFI_EBC_PROTOCOL *This, + IN OUT UINT64 *Version); + +typedef struct _EFI_EBC_PROTOCOL { + EFI_EBC_CREATE_THUNK CreateThunk; + EFI_EBC_UNLOAD_IMAGE UnloadImage; + EFI_EBC_REGISTER_ICACHE_FLUSH RegisterICacheFlush; + EFI_EBC_GET_VERSION GetVersion; +} EFI_EBC_PROTOCOL; + +#endif diff --git a/gnu-efi/inc/efipxebc.h b/gnu-efi/inc/efipxebc.h new file mode 100644 index 0000000..3760c7c --- /dev/null +++ b/gnu-efi/inc/efipxebc.h @@ -0,0 +1,482 @@ +#ifndef _EFIPXEBC_H +#define _EFIPXEBC_H + +/*++ + +Copyright (c) 1998 Intel Corporation + +Module Name: + + efipxebc.h + +Abstract: + + EFI PXE Base Code Protocol + + + +Revision History + +--*/ + +// +// PXE Base Code protocol +// + +#define EFI_PXE_BASE_CODE_PROTOCOL_GUID \ + { 0x03c4e603, 0xac28, 0x11d3, {0x9a, 0x2d, 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d} } + +INTERFACE_DECL(_EFI_PXE_BASE_CODE_PROTOCOL); + +#define DEFAULT_TTL 4 +#define DEFAULT_ToS 0 +// +// Address definitions +// + +typedef union { + UINT32 Addr[4]; + EFI_IPv4_ADDRESS v4; + EFI_IPv6_ADDRESS v6; +} EFI_IP_ADDRESS; + +typedef UINT16 EFI_PXE_BASE_CODE_UDP_PORT; + +// +// Packet definitions +// + +typedef struct { + UINT8 BootpOpcode; + UINT8 BootpHwType; + UINT8 BootpHwAddrLen; + UINT8 BootpGateHops; + UINT32 BootpIdent; + UINT16 BootpSeconds; + UINT16 BootpFlags; + UINT8 BootpCiAddr[4]; + UINT8 BootpYiAddr[4]; + UINT8 BootpSiAddr[4]; + UINT8 BootpGiAddr[4]; + UINT8 BootpHwAddr[16]; + UINT8 BootpSrvName[64]; + UINT8 BootpBootFile[128]; + UINT32 DhcpMagik; + UINT8 DhcpOptions[56]; +} EFI_PXE_BASE_CODE_DHCPV4_PACKET; + +typedef struct { + UINT32 MessageType:8; + UINT32 TransactionId:24; + UINT8 DhcpOptions[1024]; +} EFI_PXE_BASE_CODE_DHCPV6_PACKET; + +typedef union { + UINT8 Raw[1472]; + EFI_PXE_BASE_CODE_DHCPV4_PACKET Dhcpv4; + EFI_PXE_BASE_CODE_DHCPV6_PACKET Dhcpv6; +} EFI_PXE_BASE_CODE_PACKET; + +typedef struct { + UINT8 Type; + UINT8 Code; + UINT16 Checksum; + union { + UINT32 reserved; + UINT32 Mtu; + UINT32 Pointer; + struct { + UINT16 Identifier; + UINT16 Sequence; + } Echo; + } u; + UINT8 Data[494]; +} EFI_PXE_BASE_CODE_ICMP_ERROR; + +typedef struct { + UINT8 ErrorCode; + CHAR8 ErrorString[127]; +} EFI_PXE_BASE_CODE_TFTP_ERROR; + +// +// IP Receive Filter definitions +// +#define EFI_PXE_BASE_CODE_MAX_IPCNT 8 +typedef struct { + UINT8 Filters; + UINT8 IpCnt; + UINT16 reserved; + EFI_IP_ADDRESS IpList[EFI_PXE_BASE_CODE_MAX_IPCNT]; +} EFI_PXE_BASE_CODE_IP_FILTER; + +#define EFI_PXE_BASE_CODE_IP_FILTER_STATION_IP 0x0001 +#define EFI_PXE_BASE_CODE_IP_FILTER_BROADCAST 0x0002 +#define EFI_PXE_BASE_CODE_IP_FILTER_PROMISCUOUS 0x0004 +#define EFI_PXE_BASE_CODE_IP_FILTER_PROMISCUOUS_MULTICAST 0x0008 + +// +// ARP Cache definitions +// + +typedef struct { + EFI_IP_ADDRESS IpAddr; + EFI_MAC_ADDRESS MacAddr; +} EFI_PXE_BASE_CODE_ARP_ENTRY; + +typedef struct { + EFI_IP_ADDRESS IpAddr; + EFI_IP_ADDRESS SubnetMask; + EFI_IP_ADDRESS GwAddr; +} EFI_PXE_BASE_CODE_ROUTE_ENTRY; + +// +// UDP definitions +// + +#define EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_IP 0x0001 +#define EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_PORT 0x0002 +#define EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_DEST_IP 0x0004 +#define EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_DEST_PORT 0x0008 +#define EFI_PXE_BASE_CODE_UDP_OPFLAGS_USE_FILTER 0x0010 +#define EFI_PXE_BASE_CODE_UDP_OPFLAGS_MAY_FRAGMENT 0x0020 + +// +// Discover() definitions +// + +#define EFI_PXE_BASE_CODE_BOOT_TYPE_BOOTSTRAP 0 +#define EFI_PXE_BASE_CODE_BOOT_TYPE_MS_WINNT_RIS 1 +#define EFI_PXE_BASE_CODE_BOOT_TYPE_INTEL_LCM 2 +#define EFI_PXE_BASE_CODE_BOOT_TYPE_DOSUNDI 3 +#define EFI_PXE_BASE_CODE_BOOT_TYPE_NEC_ESMPRO 4 +#define EFI_PXE_BASE_CODE_BOOT_TYPE_IBM_WSoD 5 +#define EFI_PXE_BASE_CODE_BOOT_TYPE_IBM_LCCM 6 +#define EFI_PXE_BASE_CODE_BOOT_TYPE_CA_UNICENTER_TNG 7 +#define EFI_PXE_BASE_CODE_BOOT_TYPE_HP_OPENVIEW 8 +#define EFI_PXE_BASE_CODE_BOOT_TYPE_ALTIRIS_9 9 +#define EFI_PXE_BASE_CODE_BOOT_TYPE_ALTIRIS_10 10 +#define EFI_PXE_BASE_CODE_BOOT_TYPE_ALTIRIS_11 11 +#define EFI_PXE_BASE_CODE_BOOT_TYPE_NOT_USED_12 12 +#define EFI_PXE_BASE_CODE_BOOT_TYPE_REDHAT_INSTALL 13 +#define EFI_PXE_BASE_CODE_BOOT_TYPE_REDHAT_BOOT 14 +#define EFI_PXE_BASE_CODE_BOOT_TYPE_REMBO 15 +#define EFI_PXE_BASE_CODE_BOOT_TYPE_BEOBOOT 16 +// +// 17 through 32767 are reserved +// 32768 through 65279 are for vendor use +// 65280 through 65534 are reserved +// +#define EFI_PXE_BASE_CODE_BOOT_TYPE_PXETEST 65535 + +#define EFI_PXE_BASE_CODE_BOOT_LAYER_MASK 0x7FFF +#define EFI_PXE_BASE_CODE_BOOT_LAYER_INITIAL 0x0000 + + +typedef struct { + UINT16 Type; + BOOLEAN AcceptAnyResponse; + UINT8 Reserved; + EFI_IP_ADDRESS IpAddr; +} EFI_PXE_BASE_CODE_SRVLIST; + +typedef struct { + BOOLEAN UseMCast; + BOOLEAN UseBCast; + BOOLEAN UseUCast; + BOOLEAN MustUseList; + EFI_IP_ADDRESS ServerMCastIp; + UINT16 IpCnt; + EFI_PXE_BASE_CODE_SRVLIST SrvList[1]; +} EFI_PXE_BASE_CODE_DISCOVER_INFO; + +// +// Mtftp() definitions +// + +typedef enum { + EFI_PXE_BASE_CODE_TFTP_FIRST, + EFI_PXE_BASE_CODE_TFTP_GET_FILE_SIZE, + EFI_PXE_BASE_CODE_TFTP_READ_FILE, + EFI_PXE_BASE_CODE_TFTP_WRITE_FILE, + EFI_PXE_BASE_CODE_TFTP_READ_DIRECTORY, + EFI_PXE_BASE_CODE_MTFTP_GET_FILE_SIZE, + EFI_PXE_BASE_CODE_MTFTP_READ_FILE, + EFI_PXE_BASE_CODE_MTFTP_READ_DIRECTORY, + EFI_PXE_BASE_CODE_MTFTP_LAST +} EFI_PXE_BASE_CODE_TFTP_OPCODE; + +typedef struct { + EFI_IP_ADDRESS MCastIp; + EFI_PXE_BASE_CODE_UDP_PORT CPort; + EFI_PXE_BASE_CODE_UDP_PORT SPort; + UINT16 ListenTimeout; + UINT16 TransmitTimeout; +} EFI_PXE_BASE_CODE_MTFTP_INFO; + +// +// PXE Base Code Mode structure +// + +#define EFI_PXE_BASE_CODE_MAX_ARP_ENTRIES 8 +#define EFI_PXE_BASE_CODE_MAX_ROUTE_ENTRIES 8 + +typedef struct { + BOOLEAN Started; + BOOLEAN Ipv6Available; + BOOLEAN Ipv6Supported; + BOOLEAN UsingIpv6; + BOOLEAN BisSupported; + BOOLEAN BisDetected; + BOOLEAN AutoArp; + BOOLEAN SendGUID; + BOOLEAN DhcpDiscoverValid; + BOOLEAN DhcpAckReceived; + BOOLEAN ProxyOfferReceived; + BOOLEAN PxeDiscoverValid; + BOOLEAN PxeReplyReceived; + BOOLEAN PxeBisReplyReceived; + BOOLEAN IcmpErrorReceived; + BOOLEAN TftpErrorReceived; + BOOLEAN MakeCallbacks; + UINT8 TTL; + UINT8 ToS; + EFI_IP_ADDRESS StationIp; + EFI_IP_ADDRESS SubnetMask; + EFI_PXE_BASE_CODE_PACKET DhcpDiscover; + EFI_PXE_BASE_CODE_PACKET DhcpAck; + EFI_PXE_BASE_CODE_PACKET ProxyOffer; + EFI_PXE_BASE_CODE_PACKET PxeDiscover; + EFI_PXE_BASE_CODE_PACKET PxeReply; + EFI_PXE_BASE_CODE_PACKET PxeBisReply; + EFI_PXE_BASE_CODE_IP_FILTER IpFilter; + UINT32 ArpCacheEntries; + EFI_PXE_BASE_CODE_ARP_ENTRY ArpCache[EFI_PXE_BASE_CODE_MAX_ARP_ENTRIES]; + UINT32 RouteTableEntries; + EFI_PXE_BASE_CODE_ROUTE_ENTRY RouteTable[EFI_PXE_BASE_CODE_MAX_ROUTE_ENTRIES]; + EFI_PXE_BASE_CODE_ICMP_ERROR IcmpError; + EFI_PXE_BASE_CODE_TFTP_ERROR TftpError; +} EFI_PXE_BASE_CODE_MODE; + +// +// PXE Base Code Interface Function definitions +// + +typedef +EFI_STATUS +(EFIAPI *EFI_PXE_BASE_CODE_START) ( + IN struct _EFI_PXE_BASE_CODE_PROTOCOL *This, + IN BOOLEAN UseIpv6 + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_PXE_BASE_CODE_STOP) ( + IN struct _EFI_PXE_BASE_CODE_PROTOCOL *This + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_PXE_BASE_CODE_DHCP) ( + IN struct _EFI_PXE_BASE_CODE_PROTOCOL *This, + IN BOOLEAN SortOffers + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_PXE_BASE_CODE_DISCOVER) ( + IN struct _EFI_PXE_BASE_CODE_PROTOCOL *This, + IN UINT16 Type, + IN UINT16 *Layer, + IN BOOLEAN UseBis, + IN OUT EFI_PXE_BASE_CODE_DISCOVER_INFO *Info OPTIONAL + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_PXE_BASE_CODE_MTFTP) ( + IN struct _EFI_PXE_BASE_CODE_PROTOCOL *This, + IN EFI_PXE_BASE_CODE_TFTP_OPCODE Operation, + IN OUT VOID *BufferPtr OPTIONAL, + IN BOOLEAN Overwrite, + IN OUT UINT64 *BufferSize, + IN UINTN *BlockSize OPTIONAL, + IN EFI_IP_ADDRESS *ServerIp, + IN UINT8 *Filename, + IN EFI_PXE_BASE_CODE_MTFTP_INFO *Info OPTIONAL, + IN BOOLEAN DontUseBuffer + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_PXE_BASE_CODE_UDP_WRITE) ( + IN struct _EFI_PXE_BASE_CODE_PROTOCOL *This, + IN UINT16 OpFlags, + IN EFI_IP_ADDRESS *DestIp, + IN EFI_PXE_BASE_CODE_UDP_PORT *DestPort, + IN EFI_IP_ADDRESS *GatewayIp, OPTIONAL + IN EFI_IP_ADDRESS *SrcIp, OPTIONAL + IN OUT EFI_PXE_BASE_CODE_UDP_PORT *SrcPort, OPTIONAL + IN UINTN *HeaderSize, OPTIONAL + IN VOID *HeaderPtr, OPTIONAL + IN UINTN *BufferSize, + IN VOID *BufferPtr + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_PXE_BASE_CODE_UDP_READ) ( + IN struct _EFI_PXE_BASE_CODE_PROTOCOL *This, + IN UINT16 OpFlags, + IN OUT EFI_IP_ADDRESS *DestIp, OPTIONAL + IN OUT EFI_PXE_BASE_CODE_UDP_PORT *DestPort, OPTIONAL + IN OUT EFI_IP_ADDRESS *SrcIp, OPTIONAL + IN OUT EFI_PXE_BASE_CODE_UDP_PORT *SrcPort, OPTIONAL + IN UINTN *HeaderSize, OPTIONAL + IN VOID *HeaderPtr, OPTIONAL + IN OUT UINTN *BufferSize, + IN VOID *BufferPtr + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_PXE_BASE_CODE_SET_IP_FILTER) ( + IN struct _EFI_PXE_BASE_CODE_PROTOCOL *This, + IN EFI_PXE_BASE_CODE_IP_FILTER *NewFilter + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_PXE_BASE_CODE_ARP) ( + IN struct _EFI_PXE_BASE_CODE_PROTOCOL *This, + IN EFI_IP_ADDRESS *IpAddr, + IN EFI_MAC_ADDRESS *MacAddr OPTIONAL + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_PXE_BASE_CODE_SET_PARAMETERS) ( + IN struct _EFI_PXE_BASE_CODE_PROTOCOL *This, + IN BOOLEAN *NewAutoArp, OPTIONAL + IN BOOLEAN *NewSendGUID, OPTIONAL + IN UINT8 *NewTTL, OPTIONAL + IN UINT8 *NewToS, OPTIONAL + IN BOOLEAN *NewMakeCallback OPTIONAL + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_PXE_BASE_CODE_SET_STATION_IP) ( + IN struct _EFI_PXE_BASE_CODE_PROTOCOL *This, + IN EFI_IP_ADDRESS *NewStationIp, OPTIONAL + IN EFI_IP_ADDRESS *NewSubnetMask OPTIONAL + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_PXE_BASE_CODE_SET_PACKETS) ( + IN struct _EFI_PXE_BASE_CODE_PROTOCOL *This, + BOOLEAN *NewDhcpDiscoverValid, OPTIONAL + BOOLEAN *NewDhcpAckReceived, OPTIONAL + BOOLEAN *NewProxyOfferReceived, OPTIONAL + BOOLEAN *NewPxeDiscoverValid, OPTIONAL + BOOLEAN *NewPxeReplyReceived, OPTIONAL + BOOLEAN *NewPxeBisReplyReceived,OPTIONAL + IN EFI_PXE_BASE_CODE_PACKET *NewDhcpDiscover, OPTIONAL + IN EFI_PXE_BASE_CODE_PACKET *NewDhcpAck, OPTIONAL + IN EFI_PXE_BASE_CODE_PACKET *NewProxyOffer, OPTIONAL + IN EFI_PXE_BASE_CODE_PACKET *NewPxeDiscover, OPTIONAL + IN EFI_PXE_BASE_CODE_PACKET *NewPxeReply, OPTIONAL + IN EFI_PXE_BASE_CODE_PACKET *NewPxeBisReply OPTIONAL + ); + +// +// PXE Base Code Protocol structure +// + +#define EFI_PXE_BASE_CODE_PROTOCOL_REVISION 0x00010000 +#define EFI_PXE_BASE_CODE_INTERFACE_REVISION EFI_PXE_BASE_CODE_PROTOCOL_REVISION + +typedef struct _EFI_PXE_BASE_CODE_PROTOCOL { + UINT64 Revision; + EFI_PXE_BASE_CODE_START Start; + EFI_PXE_BASE_CODE_STOP Stop; + EFI_PXE_BASE_CODE_DHCP Dhcp; + EFI_PXE_BASE_CODE_DISCOVER Discover; + EFI_PXE_BASE_CODE_MTFTP Mtftp; + EFI_PXE_BASE_CODE_UDP_WRITE UdpWrite; + EFI_PXE_BASE_CODE_UDP_READ UdpRead; + EFI_PXE_BASE_CODE_SET_IP_FILTER SetIpFilter; + EFI_PXE_BASE_CODE_ARP Arp; + EFI_PXE_BASE_CODE_SET_PARAMETERS SetParameters; + EFI_PXE_BASE_CODE_SET_STATION_IP SetStationIp; + EFI_PXE_BASE_CODE_SET_PACKETS SetPackets; + EFI_PXE_BASE_CODE_MODE *Mode; +} EFI_PXE_BASE_CODE_PROTOCOL; + +// Note: Because it conflicted with the EDK2 struct name, the +// 'EFI_PXE_BASE_CODE_PROTOCOL' GUID definition, from older +// versions of gnu-efi, is now obsoleted. +// Use 'EFI_PXE_BASE_CODE_PROTOCOL_GUID' instead. + +typedef struct _EFI_PXE_BASE_CODE_PROTOCOL _EFI_PXE_BASE_CODE; +typedef struct _EFI_PXE_BASE_CODE_PROTOCOL EFI_PXE_BASE_CODE; + +// +// Call Back Definitions +// + +#define EFI_PXE_BASE_CODE_CALLBACK_PROTOCOL_GUID \ + { 0x245dca21, 0xfb7b, 0x11d3, {0x8f, 0x01, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b} } + +// +// Revision Number +// + +#define EFI_PXE_BASE_CODE_CALLBACK_PROTOCOL_REVISION 0x00010000 +#define EFI_PXE_BASE_CODE_CALLBACK_INTERFACE_REVISION EFI_PXE_BASE_CODE_CALLBACK_PROTOCOL_REVISION + +INTERFACE_DECL(_EFI_PXE_BASE_CODE_CALLBACK_PROTOCOL); + +typedef enum { + EFI_PXE_BASE_CODE_FUNCTION_FIRST, + EFI_PXE_BASE_CODE_FUNCTION_DHCP, + EFI_PXE_BASE_CODE_FUNCTION_DISCOVER, + EFI_PXE_BASE_CODE_FUNCTION_MTFTP, + EFI_PXE_BASE_CODE_FUNCTION_UDP_WRITE, + EFI_PXE_BASE_CODE_FUNCTION_UDP_READ, + EFI_PXE_BASE_CODE_FUNCTION_ARP, + EFI_PXE_BASE_CODE_FUNCTION_IGMP, + EFI_PXE_BASE_CODE_PXE_FUNCTION_LAST +} EFI_PXE_BASE_CODE_FUNCTION; + +typedef enum { + EFI_PXE_BASE_CODE_CALLBACK_STATUS_FIRST, + EFI_PXE_BASE_CODE_CALLBACK_STATUS_CONTINUE, + EFI_PXE_BASE_CODE_CALLBACK_STATUS_ABORT, + EFI_PXE_BASE_CODE_CALLBACK_STATUS_LAST +} EFI_PXE_BASE_CODE_CALLBACK_STATUS; + +typedef +EFI_PXE_BASE_CODE_CALLBACK_STATUS +(EFIAPI *EFI_PXE_CALLBACK) ( + IN struct _EFI_PXE_BASE_CODE_CALLBACK_PROTOCOL *This, + IN EFI_PXE_BASE_CODE_FUNCTION Function, + IN BOOLEAN Received, + IN UINT32 PacketLen, + IN EFI_PXE_BASE_CODE_PACKET *Packet OPTIONAL + ); + +typedef struct _EFI_PXE_BASE_CODE_CALLBACK_PROTOCOL { + UINT64 Revision; + EFI_PXE_CALLBACK Callback; +} EFI_PXE_BASE_CODE_CALLBACK_PROTOCOL; + +// Note: Because it conflicted with the EDK2 struct name, the +// 'EFI_PXE_BASE_CODE_CALLBACK_PROTOCOL' GUID definition, from +// older versions of gnu-efi, is now obsoleted. +// Use 'EFI_PXE_BASE_CODE_CALLBACK_PROTOCOL_GUID' instead. + +typedef struct _EFI_PXE_BASE_CODE_CALLBACK_PROTOCOL _EFI_PXE_BASE_CODE_CALLBACK; +typedef EFI_PXE_BASE_CODE_CALLBACK_PROTOCOL EFI_PXE_BASE_CODE_CALLBACK; + +#endif /* _EFIPXEBC_H */ diff --git a/gnu-efi/inc/efirtlib.h b/gnu-efi/inc/efirtlib.h new file mode 100644 index 0000000..49d0b4d --- /dev/null +++ b/gnu-efi/inc/efirtlib.h @@ -0,0 +1,179 @@ +#ifndef _EFI_RT_LIB_INCLUDE_ +#define _EFI_RT_LIB_INCLUDE_ +/*++ + +Copyright (c) 1998 Intel Corporation + +Module Name: + + efilib.h + +Abstract: + + EFI Runtime library functions + + + +Revision History + +--*/ + +#include "efidebug.h" +#include "efipart.h" +#include "efilibplat.h" + + +VOID +RUNTIMEFUNCTION +RtZeroMem ( + IN VOID *Buffer, + IN UINTN Size + ); + +VOID +RUNTIMEFUNCTION +RtSetMem ( + IN VOID *Buffer, + IN UINTN Size, + IN UINT8 Value + ); + +VOID +RUNTIMEFUNCTION +RtCopyMem ( + IN VOID *Dest, + IN CONST VOID *Src, + IN UINTN len + ); + +INTN +RUNTIMEFUNCTION +RtCompareMem ( + IN CONST VOID *Dest, + IN CONST VOID *Src, + IN UINTN len + ); + +INTN +RUNTIMEFUNCTION +RtStrCmp ( + IN CONST CHAR16 *s1, + IN CONST CHAR16 *s2 + ); + + +VOID +RUNTIMEFUNCTION +RtStrCpy ( + IN CHAR16 *Dest, + IN CONST CHAR16 *Src + ); + +VOID +RUNTIMEFUNCTION +RtStrnCpy ( + IN CHAR16 *Dest, + IN CONST CHAR16 *Src, + IN UINTN Len + ); + +CHAR16 * +RUNTIMEFUNCTION +RtStpCpy ( + IN CHAR16 *Dest, + IN CONST CHAR16 *Src + ); + +CHAR16 * +RUNTIMEFUNCTION +RtStpnCpy ( + IN CHAR16 *Dest, + IN CONST CHAR16 *Src, + IN UINTN Len + ); + +VOID +RUNTIMEFUNCTION +RtStrCat ( + IN CHAR16 *Dest, + IN CONST CHAR16 *Src + ); + +VOID +RUNTIMEFUNCTION +RtStrnCat ( + IN CHAR16 *Dest, + IN CONST CHAR16 *Src, + IN UINTN Len + ); + +UINTN +RUNTIMEFUNCTION +RtStrLen ( + IN CONST CHAR16 *s1 + ); + +UINTN +RUNTIMEFUNCTION +RtStrnLen ( + IN CONST CHAR16 *s1, + IN UINTN Len + ); + +UINTN +RUNTIMEFUNCTION +RtStrSize ( + IN CONST CHAR16 *s1 + ); + +INTN +RUNTIMEFUNCTION +RtCompareGuid ( + IN EFI_GUID *Guid1, + IN EFI_GUID *Guid2 + ); + +UINT8 +RUNTIMEFUNCTION +RtDecimaltoBCD( + IN UINT8 BcdValue + ); + +UINT8 +RUNTIMEFUNCTION +RtBCDtoDecimal( + IN UINT8 BcdValue + ); + +// +// Virtual mapping transition support. (Only used during +// the virtual address change transisition) +// + +VOID +RUNTIMEFUNCTION +RtLibEnableVirtualMappings ( + VOID + ); + +VOID +RUNTIMEFUNCTION +RtConvertList ( + IN UINTN DebugDisposition, + IN OUT LIST_ENTRY *ListHead + ); + +VOID +RUNTIMEFUNCTION +RtAcquireLock ( + IN FLOCK *Lock + ); + +VOID +RUNTIMEFUNCTION +RtReleaseLock ( + IN FLOCK *Lock + ); + + +#endif diff --git a/gnu-efi/inc/efiser.h b/gnu-efi/inc/efiser.h new file mode 100644 index 0000000..45a463e --- /dev/null +++ b/gnu-efi/inc/efiser.h @@ -0,0 +1,136 @@ +#ifndef _EFI_SER_H +#define _EFI_SER_H + +/*++ + +Copyright (c) 1998 Intel Corporation + +Module Name: + + efiser.h + +Abstract: + + EFI serial protocol + +Revision History + +--*/ + +// +// Serial protocol +// + +#define EFI_SERIAL_IO_PROTOCOL_GUID \ + { 0xBB25CF6F, 0xF1D4, 0x11D2, {0x9A, 0x0C, 0x00, 0x90, 0x27, 0x3F, 0xC1, 0xFD} } +#define SERIAL_IO_PROTOCOL EFI_SERIAL_IO_PROTOCOL_GUID + +INTERFACE_DECL(_EFI_SERIAL_IO_PROTOCOL); + +typedef enum { + DefaultParity, + NoParity, + EvenParity, + OddParity, + MarkParity, + SpaceParity +} EFI_PARITY_TYPE; + +typedef enum { + DefaultStopBits, + OneStopBit, // 1 stop bit + OneFiveStopBits, // 1.5 stop bits + TwoStopBits // 2 stop bits +} EFI_STOP_BITS_TYPE; + +#define EFI_SERIAL_CLEAR_TO_SEND 0x0010 // RO +#define EFI_SERIAL_DATA_SET_READY 0x0020 // RO +#define EFI_SERIAL_RING_INDICATE 0x0040 // RO +#define EFI_SERIAL_CARRIER_DETECT 0x0080 // RO +#define EFI_SERIAL_REQUEST_TO_SEND 0x0002 // WO +#define EFI_SERIAL_DATA_TERMINAL_READY 0x0001 // WO +#define EFI_SERIAL_INPUT_BUFFER_EMPTY 0x0100 // RO +#define EFI_SERIAL_OUTPUT_BUFFER_EMPTY 0x0200 // RO +#define EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE 0x1000 // RW +#define EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE 0x2000 // RW +#define EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE 0x4000 // RW + +typedef +EFI_STATUS +(EFIAPI *EFI_SERIAL_RESET) ( + IN struct _EFI_SERIAL_IO_PROTOCOL *This + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_SERIAL_SET_ATTRIBUTES) ( + IN struct _EFI_SERIAL_IO_PROTOCOL *This, + IN UINT64 BaudRate, + IN UINT32 ReceiveFifoDepth, + IN UINT32 Timeout, + IN EFI_PARITY_TYPE Parity, + IN UINT8 DataBits, + IN EFI_STOP_BITS_TYPE StopBits + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_SERIAL_SET_CONTROL_BITS) ( + IN struct _EFI_SERIAL_IO_PROTOCOL *This, + IN UINT32 Control + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_SERIAL_GET_CONTROL_BITS) ( + IN struct _EFI_SERIAL_IO_PROTOCOL *This, + OUT UINT32 *Control + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_SERIAL_WRITE) ( + IN struct _EFI_SERIAL_IO_PROTOCOL *This, + IN OUT UINTN *BufferSize, + IN VOID *Buffer + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_SERIAL_READ) ( + IN struct _EFI_SERIAL_IO_PROTOCOL *This, + IN OUT UINTN *BufferSize, + OUT VOID *Buffer + ); + +typedef struct { + UINT32 ControlMask; + + // current Attributes + UINT32 Timeout; + UINT64 BaudRate; + UINT32 ReceiveFifoDepth; + UINT32 DataBits; + UINT32 Parity; + UINT32 StopBits; +} SERIAL_IO_MODE; + +#define SERIAL_IO_INTERFACE_REVISION 0x00010000 + +typedef struct _EFI_SERIAL_IO_PROTOCOL { + UINT32 Revision; + EFI_SERIAL_RESET Reset; + EFI_SERIAL_SET_ATTRIBUTES SetAttributes; + EFI_SERIAL_SET_CONTROL_BITS SetControl; + EFI_SERIAL_GET_CONTROL_BITS GetControl; + EFI_SERIAL_WRITE Write; + EFI_SERIAL_READ Read; + + SERIAL_IO_MODE *Mode; +} EFI_SERIAL_IO_PROTOCOL; + +typedef struct _EFI_SERIAL_IO_PROTOCOL _SERIAL_IO_INTERFACE; +typedef EFI_SERIAL_IO_PROTOCOL SERIAL_IO_INTERFACE; + +#endif + diff --git a/gnu-efi/inc/efisetjmp.h b/gnu-efi/inc/efisetjmp.h new file mode 100644 index 0000000..de69194 --- /dev/null +++ b/gnu-efi/inc/efisetjmp.h @@ -0,0 +1,10 @@ +#ifndef GNU_EFI_SETJMP_H +#define GNU_EFI_SETJMP_H + +#include "eficompiler.h" +#include "efisetjmp_arch.h" + +extern UINTN setjmp(jmp_buf env) __attribute__((returns_twice)); +extern VOID longjmp(jmp_buf env, UINTN value) __attribute__((noreturn)); + +#endif /* GNU_EFI_SETJMP_H */ diff --git a/gnu-efi/inc/efishellintf.h b/gnu-efi/inc/efishellintf.h new file mode 100644 index 0000000..e649acd --- /dev/null +++ b/gnu-efi/inc/efishellintf.h @@ -0,0 +1,94 @@ +/** @file + SHELL_INTERFACE_PROTOCOL from EDK shell (no spec). + + Shell Interface - additional information (over image_info) provided + to an application started by the shell. + + ConIo provides a file-style interface to the console. + + The shell interface's and data (including ConIo) are only valid during + the applications Entry Point. Once the application returns from it's + entry point the data is freed by the invoking shell. + + Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ +/* + * This is based on ShellPkg/Include/Protocol/EfiShellInterface.h from EDK II. + */ + +#ifndef _SHELLINTERFACE_H_ +#define _SHELLINTERFACE_H_ + + +#define SHELL_INTERFACE_PROTOCOL_GUID \ + { \ + 0x47c7b223, 0xc42a, 0x11d2, {0x8e, 0x57, 0x0, 0xa0, 0xc9, 0x69, 0x72, 0x3b} \ + } + +/// +/// Bit definitions for EFI_SHELL_ARG_INFO +/// +typedef enum { + ARG_NO_ATTRIB = 0x0, + ARG_IS_QUOTED = 1<<0, + ARG_PARTIALLY_QUOTED = 1<<1, + ARG_FIRST_HALF_QUOTED = 1<<2, + ARG_FIRST_CHAR_IS_ESC = 1<<3 +} EFI_SHELL_ARG_INFO_TYPES; + +/// +/// Attributes for an argument. +/// +typedef struct _EFI_SHELL_ARG_INFO { + UINT32 Attributes; +} EFI_SHELL_ARG_INFO; + +/// +/// This protocol provides access to additional information about a shell application. +/// +typedef struct { + /// + /// Handle back to original image handle & image information. + /// + EFI_HANDLE ImageHandle; + EFI_LOADED_IMAGE *Info; + + /// + /// Parsed arg list converted more C-like format. + /// + CHAR16 **Argv; + UINTN Argc; + + /// + /// Storage for file redirection args after parsing. + /// + CHAR16 **RedirArgv; + UINTN RedirArgc; + + /// + /// A file style handle for console io. + /// + EFI_FILE *StdIn; + EFI_FILE *StdOut; + EFI_FILE *StdErr; + + /// + /// List of attributes for each argument. + /// + EFI_SHELL_ARG_INFO *ArgInfo; + + /// + /// Whether we are echoing. + /// + BOOLEAN EchoOn; +} EFI_SHELL_INTERFACE; + +#endif diff --git a/gnu-efi/inc/efishellparm.h b/gnu-efi/inc/efishellparm.h new file mode 100644 index 0000000..da120e5 --- /dev/null +++ b/gnu-efi/inc/efishellparm.h @@ -0,0 +1,63 @@ +/** @file + EFI_SHELL_PARAMETERS_PROTOCOL as defined in the UEFI Shell 2.0 specification. + + Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ +/* + * This is based on ShellPkg/Include/Protocol/EfiShellParameters.h from EDK II. + */ + +#ifndef __EFI_SHELL_PARAMETERS_PROTOCOL__ +#define __EFI_SHELL_PARAMETERS_PROTOCOL__ + + +// EDK2's ShellBase.h +typedef VOID *SHELL_FILE_HANDLE; + +#define EFI_SHELL_PARAMETERS_PROTOCOL_GUID \ + { \ + 0x752f3136, 0x4e16, 0x4fdc, { 0xa2, 0x2a, 0xe5, 0xf4, 0x68, 0x12, 0xf4, 0xca } \ + } + +typedef struct _EFI_SHELL_PARAMETERS_PROTOCOL { + /// + /// Points to an Argc-element array of points to NULL-terminated strings containing + /// the command-line parameters. The first entry in the array is always the full file + /// path of the executable. Any quotation marks that were used to preserve + /// whitespace have been removed. + /// + CHAR16 **Argv; + + /// + /// The number of elements in the Argv array. + /// + UINTN Argc; + + /// + /// The file handle for the standard input for this executable. This may be different + /// from the ConInHandle in EFI_SYSTEM_TABLE. + /// + SHELL_FILE_HANDLE StdIn; + + /// + /// The file handle for the standard output for this executable. This may be different + /// from the ConOutHandle in EFI_SYSTEM_TABLE. + /// + SHELL_FILE_HANDLE StdOut; + + /// + /// The file handle for the standard error output for this executable. This may be + /// different from the StdErrHandle in EFI_SYSTEM_TABLE. + /// + SHELL_FILE_HANDLE StdErr; +} EFI_SHELL_PARAMETERS_PROTOCOL; + +#endif diff --git a/gnu-efi/inc/efistdarg.h b/gnu-efi/inc/efistdarg.h new file mode 100644 index 0000000..bb04b31 --- /dev/null +++ b/gnu-efi/inc/efistdarg.h @@ -0,0 +1,33 @@ +#ifndef _EFISTDARG_H_ +#define _EFISTDARG_H_ + +/*++ + +Copyright (c) 1998 Intel Corporation + +Module Name: + + devpath.h + +Abstract: + + Defines for parsing the EFI Device Path structures + + + +Revision History + +--*/ + +#ifndef GNU_EFI_USE_EXTERNAL_STDARG +typedef __builtin_va_list va_list; + +# define va_start(v,l) __builtin_va_start(v,l) +# define va_end(v) __builtin_va_end(v) +# define va_arg(v,l) __builtin_va_arg(v,l) +# define va_copy(d,s) __builtin_va_copy(d,s) +#else +# include +#endif + +#endif diff --git a/gnu-efi/inc/efitcp.h b/gnu-efi/inc/efitcp.h new file mode 100644 index 0000000..6c5df7f --- /dev/null +++ b/gnu-efi/inc/efitcp.h @@ -0,0 +1,391 @@ +#ifndef _EFI_TCP_H +#define _EFI_TCP_H + +/*++ +Copyright (c) 2013 Intel Corporation + +--*/ + +#define EFI_TCP4_SERVICE_BINDING_PROTOCOL \ + { 0x00720665, 0x67eb, 0x4a99, {0xba, 0xf7, 0xd3, 0xc3, 0x3a, 0x1c,0x7c, 0xc9}} + +#define EFI_TCP4_PROTOCOL \ + { 0x65530bc7, 0xa359, 0x410f, {0xb0, 0x10, 0x5a, 0xad, 0xc7, 0xec, 0x2b, 0x62}} + +#define EFI_TCP6_SERVICE_BINDING_PROTOCOL \ + { 0xec20eb79, 0x6c1a, 0x4664, {0x9a, 0xd, 0xd2, 0xe4, 0xcc, 0x16, 0xd6, 0x64}} + +#define EFI_TCP6_PROTOCOL \ + { 0x46e44855, 0xbd60, 0x4ab7, {0xab, 0xd, 0xa6, 0x79, 0xb9, 0x44, 0x7d, 0x77}} + +INTERFACE_DECL(_EFI_TCP4); +INTERFACE_DECL(_EFI_TCP6); + +typedef struct { + BOOLEAN UseDefaultAddress; + EFI_IPv4_ADDRESS StationAddress; + EFI_IPv4_ADDRESS SubnetMask; + UINT16 StationPort; + EFI_IPv4_ADDRESS RemoteAddress; + UINT16 RemotePort; + BOOLEAN ActiveFlag; +} EFI_TCP4_ACCESS_POINT; + +typedef struct { + UINT32 ReceiveBufferSize; + UINT32 SendBufferSize; + UINT32 MaxSynBackLog; + UINT32 ConnectionTimeout; + UINT32 DataRetries; + UINT32 FinTimeout; + UINT32 TimeWaitTimeout; + UINT32 KeepAliveProbes; + UINT32 KeepAliveTime; + UINT32 KeepAliveInterval; + BOOLEAN EnableNagle; + BOOLEAN EnableTimeStamp; + BOOLEAN EnableWindowScaling; + BOOLEAN EnableSelectiveAck; + BOOLEAN EnablePAthMtuDiscovery; +} EFI_TCP4_OPTION; + +typedef struct { + // Receiving Filters + // I/O parameters + UINT8 TypeOfService; + UINT8 TimeToLive; + + // Access Point + EFI_TCP4_ACCESS_POINT AccessPoint; + + // TCP Control Options + EFI_TCP4_OPTION *ControlOption; +} EFI_TCP4_CONFIG_DATA; + +typedef enum { + Tcp4StateClosed = 0, + Tcp4StateListen = 1, + Tcp4StateSynSent = 2, + Tcp4StateSynReceived = 3, + Tcp4StateEstablished = 4, + Tcp4StateFinWait1 = 5, + Tcp4StateFinWait2 = 6, + Tcp4StateClosing = 7, + Tcp4StateTimeWait = 8, + Tcp4StateCloseWait = 9, + Tcp4StateLastAck = 10 +} EFI_TCP4_CONNECTION_STATE; + +typedef +EFI_STATUS +(EFIAPI *EFI_TCP4_GET_MODE_DATA) ( + IN struct _EFI_TCP4 *This, + OUT EFI_TCP4_CONNECTION_STATE *Tcp4State OPTIONAL, + OUT EFI_TCP4_CONFIG_DATA *Tcp4ConfigData OPTIONAL, + OUT EFI_IP4_MODE_DATA *Ip4ModeData OPTIONAL, + OUT EFI_MANAGED_NETWORK_CONFIG_DATA *MnpConfigData OPTIONAL, + OUT EFI_SIMPLE_NETWORK_MODE *SnpModeData OPTIONAL + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_TCP4_CONFIGURE) ( + IN struct _EFI_TCP4 *This, + IN EFI_TCP4_CONFIG_DATA *TcpConfigData OPTIONAL + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_TCP4_ROUTES) ( + IN struct _EFI_TCP4 *This, + IN BOOLEAN DeleteRoute, + IN EFI_IPv4_ADDRESS *SubnetAddress, + IN EFI_IPv4_ADDRESS *SubnetMask, + IN EFI_IPv4_ADDRESS *GatewayAddress +); + +typedef struct { + EFI_EVENT Event; + EFI_STATUS Status; +} EFI_TCP4_COMPLETION_TOKEN; + +typedef struct { + EFI_TCP4_COMPLETION_TOKEN CompletionToken; +} EFI_TCP4_CONNECTION_TOKEN; + +typedef +EFI_STATUS +(EFIAPI *EFI_TCP4_CONNECT) ( + IN struct _EFI_TCP4 *This, + IN EFI_TCP4_CONNECTION_TOKEN *ConnectionToken + ); + +typedef struct { + EFI_TCP4_COMPLETION_TOKEN CompletionToken; + EFI_HANDLE NewChildHandle; +} EFI_TCP4_LISTEN_TOKEN; + +typedef +EFI_STATUS +(EFIAPI *EFI_TCP4_ACCEPT) ( + IN struct _EFI_TCP4 *This, + IN EFI_TCP4_LISTEN_TOKEN *ListenToken + ); + +#define EFI_CONNECTION_FIN EFIERR(104) +#define EFI_CONNECTION_RESET EFIERR(105) +#define EFI_CONNECTION_REFUSED EFIERR(106) + +typedef struct { + UINT32 FragmentLength; + VOID *FragmentBuffer; +} EFI_TCP4_FRAGMENT_DATA; + +typedef struct { + BOOLEAN UrgentFlag; + UINT32 DataLength; + UINT32 FragmentCount; + EFI_TCP4_FRAGMENT_DATA FragmentTable[1]; +} EFI_TCP4_RECEIVE_DATA; + +typedef struct { + BOOLEAN Push; + BOOLEAN Urgent; + UINT32 DataLength; + UINT32 FragmentCount; + EFI_TCP4_FRAGMENT_DATA FragmentTable[1]; +} EFI_TCP4_TRANSMIT_DATA; + +typedef struct { + EFI_TCP4_COMPLETION_TOKEN CompletionToken; + union { + EFI_TCP4_RECEIVE_DATA *RxData; + EFI_TCP4_TRANSMIT_DATA *TxData; + } Packet; +} EFI_TCP4_IO_TOKEN; + +typedef +EFI_STATUS +(EFIAPI *EFI_TCP4_TRANSMIT) ( + IN struct _EFI_TCP4 *This, + IN EFI_TCP4_IO_TOKEN *Token + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_TCP4_RECEIVE) ( + IN struct _EFI_TCP4 *This, + IN EFI_TCP4_IO_TOKEN *Token + ); + +typedef struct { + EFI_TCP4_COMPLETION_TOKEN CompletionToken; + BOOLEAN AbortOnClose; +} EFI_TCP4_CLOSE_TOKEN; + +typedef +EFI_STATUS +(EFIAPI *EFI_TCP4_CLOSE)( + IN struct _EFI_TCP4 *This, + IN EFI_TCP4_CLOSE_TOKEN *CloseToken + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_TCP4_CANCEL)( + IN struct _EFI_TCP4 *This, + IN EFI_TCP4_COMPLETION_TOKEN *Token OPTIONAL +); + +typedef +EFI_STATUS +(EFIAPI *EFI_TCP4_POLL) ( + IN struct _EFI_TCP4 *This + ); + +typedef struct _EFI_TCP4 { + EFI_TCP4_GET_MODE_DATA GetModeData; + EFI_TCP4_CONFIGURE Configure; + EFI_TCP4_ROUTES Routes; + EFI_TCP4_CONNECT Connect; + EFI_TCP4_ACCEPT Accept; + EFI_TCP4_TRANSMIT Transmit; + EFI_TCP4_RECEIVE Receive; + EFI_TCP4_CLOSE Close; + EFI_TCP4_CANCEL Cancel; + EFI_TCP4_POLL Poll; +} EFI_TCP4; + +typedef enum { + Tcp6StateClosed = 0, + Tcp6StateListen = 1, + Tcp6StateSynSent = 2, + Tcp6StateSynReceived = 3, + Tcp6StateEstablished = 4, + Tcp6StateFinWait1 = 5, + Tcp6StateFinWait2 = 6, + Tcp6StateClosing = 7, + Tcp6StateTimeWait = 8, + Tcp6StateCloseWait = 9, + Tcp6StateLastAck = 10 +} EFI_TCP6_CONNECTION_STATE; + +typedef struct { + EFI_IPv6_ADDRESS StationAddress; + UINT16 StationPort; + EFI_IPv6_ADDRESS RemoteAddress; + UINT16 RemotePort; + BOOLEAN ActiveFlag; +} EFI_TCP6_ACCESS_POINT; + +typedef struct { + UINT32 ReceiveBufferSize; + UINT32 SendBufferSize; + UINT32 MaxSynBackLog; + UINT32 ConnectionTimeout; + UINT32 DataRetries; + UINT32 FinTimeout; + UINT32 TimeWaitTimeout; + UINT32 KeepAliveProbes; + UINT32 KeepAliveTime; + UINT32 KeepAliveInterval; + BOOLEAN EnableNagle; + BOOLEAN EnableTimeStamp; + BOOLEAN EnableWindbowScaling; + BOOLEAN EnableSelectiveAck; + BOOLEAN EnablePathMtuDiscovery; +} EFI_TCP6_OPTION; + +typedef struct { + UINT8 TrafficClass; + UINT8 HopLimit; + EFI_TCP6_ACCESS_POINT AccessPoint; + EFI_TCP6_OPTION *ControlOption; +} EFI_TCP6_CONFIG_DATA; + +typedef +EFI_STATUS +(EFIAPI *EFI_TCP6_GET_MODE_DATA) ( + IN struct _EFI_TCP6 *This, + OUT EFI_TCP6_CONNECTION_STATE *Tcp6State OPTIONAL, + OUT EFI_TCP6_CONFIG_DATA *Tcp6ConfigData OPTIONAL, + OUT EFI_IP6_MODE_DATA *Ip6ModeData OPTIONAL, + OUT EFI_MANAGED_NETWORK_CONFIG_DATA *MnpConfigData OPTIONAL, + OUT EFI_SIMPLE_NETWORK_MODE *SnpModeData OPTIONAL + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_TCP6_CONFIGURE) ( + IN struct _EFI_TCP6 *This, + IN EFI_TCP6_CONFIG_DATA *Tcp6ConfigData OPTIONAL + ); + +typedef struct { + EFI_EVENT Event; + EFI_STATUS Status; +} EFI_TCP6_COMPLETION_TOKEN; + +typedef struct { + EFI_TCP6_COMPLETION_TOKEN CompletionToken; +} EFI_TCP6_CONNECTION_TOKEN; + +typedef +EFI_STATUS +(EFIAPI *EFI_TCP6_CONNECT) ( + IN struct _EFI_TCP6 *This, + IN EFI_TCP6_CONNECTION_TOKEN *ConnectionToken + ); + +typedef struct { + EFI_TCP6_COMPLETION_TOKEN CompletionToken; + EFI_HANDLE NewChildHandle; +} EFI_TCP6_LISTEN_TOKEN; + +typedef +EFI_STATUS +(EFIAPI *EFI_TCP6_ACCEPT) ( + IN struct _EFI_TCP6 *This, + IN EFI_TCP6_LISTEN_TOKEN *ListenToken + ); + +typedef struct { + UINT32 FragmentLength; + VOID *FragmentBuffer; +} EFI_TCP6_FRAGMENT_DATA; + +typedef struct { + BOOLEAN UrgentFlag; + UINT32 DataLength; + UINT32 FragmentCount; + EFI_TCP6_FRAGMENT_DATA FragmentTable[1]; +} EFI_TCP6_RECEIVE_DATA; + +typedef struct { + BOOLEAN Push; + BOOLEAN Urgent; + UINT32 DataLength; + UINT32 FragmentCount; + EFI_TCP6_FRAGMENT_DATA FragmentTable[1]; +} EFI_TCP6_TRANSMIT_DATA; + +typedef struct { + EFI_TCP6_COMPLETION_TOKEN CompletionToken; + union { + EFI_TCP6_RECEIVE_DATA *RxData; + EFI_TCP6_TRANSMIT_DATA *TxData; + } Packet; +} EFI_TCP6_IO_TOKEN; + +typedef +EFI_STATUS +(EFIAPI *EFI_TCP6_TRANSMIT) ( + IN struct _EFI_TCP6 *This, + IN EFI_TCP6_IO_TOKEN *Token + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_TCP6_RECEIVE) ( + IN struct _EFI_TCP6 *This, + IN EFI_TCP6_IO_TOKEN *Token + ); + +typedef struct { + EFI_TCP6_COMPLETION_TOKEN CompletionToken; + BOOLEAN AbortOnClose; +} EFI_TCP6_CLOSE_TOKEN; + +typedef +EFI_STATUS +(EFIAPI *EFI_TCP6_CLOSE)( + IN struct _EFI_TCP6 *This, + IN EFI_TCP6_CLOSE_TOKEN *CloseToken + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_TCP6_CANCEL)( + IN struct _EFI_TCP6 *This, + IN EFI_TCP6_COMPLETION_TOKEN *Token OPTIONAL + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_TCP6_POLL) ( + IN struct _EFI_TCP6 *This + ); + +typedef struct _EFI_TCP6 { + EFI_TCP6_GET_MODE_DATA GetModeData; + EFI_TCP6_CONFIGURE Configure; + EFI_TCP6_CONNECT Connect; + EFI_TCP6_ACCEPT Accept; + EFI_TCP6_TRANSMIT Transmit; + EFI_TCP6_RECEIVE Receive; + EFI_TCP6_CLOSE Close; + EFI_TCP6_CANCEL Cancel; + EFI_TCP6_POLL Poll; +} EFI_TCP6; + +#endif /* _EFI_TCP_H */ diff --git a/gnu-efi/inc/efiudp.h b/gnu-efi/inc/efiudp.h new file mode 100644 index 0000000..7c8b467 --- /dev/null +++ b/gnu-efi/inc/efiudp.h @@ -0,0 +1,272 @@ +#ifndef _EFI_UDP_H +#define _EFI_UDP_H + + +/*++ +Copyright (c) 2013 Intel Corporation + +--*/ + +#define EFI_UDP4_SERVICE_BINDING_PROTOCOL \ + { 0x83f01464, 0x99bd, 0x45e5, {0xb3, 0x83, 0xaf, 0x63, 0x05, 0xd8, 0xe9, 0xe6} } + +#define EFI_UDP4_PROTOCOL \ + { 0x3ad9df29, 0x4501, 0x478d, {0xb1, 0xf8, 0x7f, 0x7f, 0xe7, 0x0e, 0x50, 0xf3} } + +#define EFI_UDP6_SERVICE_BINDING_PROTOCOL \ + { 0x66ed4721, 0x3c98, 0x4d3e, {0x81, 0xe3, 0xd0, 0x3d, 0xd3, 0x9a, 0x72, 0x54} } + +#define EFI_UDP6_PROTOCOL \ + { 0x4f948815, 0xb4b9, 0x43cb, {0x8a, 0x33, 0x90, 0xe0, 0x60, 0xb3,0x49, 0x55} } + +INTERFACE_DECL(_EFI_UDP4); +INTERFACE_DECL(_EFI_UDP6); + +typedef struct { + BOOLEAN AcceptBroadcast; + BOOLEAN AcceptPromiscuous; + BOOLEAN AcceptAnyPort; + BOOLEAN AllowDuplicatePort; + UINT8 TypeOfService; + UINT8 TimeToLive; + BOOLEAN DoNotFragment; + UINT32 ReceiveTimeout; + UINT32 TransmitTimeout; + BOOLEAN UseDefaultAddress; + EFI_IPv4_ADDRESS StationAddress; + EFI_IPv4_ADDRESS SubnetMask; + UINT16 StationPort; + EFI_IPv4_ADDRESS RemoteAddress; + UINT16 RemotePort; +} EFI_UDP4_CONFIG_DATA; + +typedef +EFI_STATUS +(EFIAPI *EFI_UDP4_GET_MODE_DATA) ( + IN struct _EFI_UDP4 *This, + OUT EFI_UDP4_CONFIG_DATA *Udp4ConfigData OPTIONAL, + OUT EFI_IP4_MODE_DATA *Ip4ModeData OPTIONAL, + OUT EFI_MANAGED_NETWORK_CONFIG_DATA *MnpConfigData OPTIONAL, + OUT EFI_SIMPLE_NETWORK_MODE *SnpModeData OPTIONAL + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_UDP4_CONFIGURE) ( + IN struct _EFI_UDP4 *This, + IN EFI_UDP4_CONFIG_DATA *UdpConfigData OPTIONAL + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_UDP4_GROUPS) ( + IN struct _EFI_UDP4 *This, + IN BOOLEAN JoinFlag, + IN EFI_IPv4_ADDRESS *MulticastAddress OPTIONAL + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_UDP4_ROUTES) ( + IN struct _EFI_UDP4 *This, + IN BOOLEAN DeleteRoute, + IN EFI_IPv4_ADDRESS *SubnetAddress, + IN EFI_IPv4_ADDRESS *SubnetMask, + IN EFI_IPv4_ADDRESS *GatewayAddress + ); + +#define EFI_NETWORK_UNREACHABLE EFIERR(100) +#define EFI_HOST_UNREACHABLE EFIERR(101) +#define EFI_PROTOCOL_UNREACHABLE EFIERR(102) +#define EFI_PORT_UNREACHABLE EFIERR(103) + +typedef struct { + EFI_IPv4_ADDRESS SourceAddress; + UINT16 SourcePort; + EFI_IPv4_ADDRESS DestinationAddress; + UINT16 DestinationPort; +} EFI_UDP4_SESSION_DATA; + +typedef struct { + UINT32 FragmentLength; + VOID *FragmentBuffer; +} EFI_UDP4_FRAGMENT_DATA; + +typedef struct { + EFI_TIME TimeStamp; + EFI_EVENT RecycleSignal; + EFI_UDP4_SESSION_DATA UdpSession; + UINT32 DataLength; + UINT32 FragmentCount; + EFI_UDP4_FRAGMENT_DATA FragmentTable[1]; +} EFI_UDP4_RECEIVE_DATA; + +typedef struct { + EFI_UDP4_SESSION_DATA *UdpSessionData; + EFI_IPv4_ADDRESS *GatewayAddress; + UINT32 DataLength; + UINT32 FragmentCount; + EFI_UDP4_FRAGMENT_DATA FragmentTable[1]; +} EFI_UDP4_TRANSMIT_DATA; + +typedef struct { + EFI_EVENT Event; + EFI_STATUS Status; + union { + EFI_UDP4_RECEIVE_DATA *RxData; + EFI_UDP4_TRANSMIT_DATA *TxData; + } Packet; +} EFI_UDP4_COMPLETION_TOKEN; + +typedef +EFI_STATUS +(EFIAPI *EFI_UDP4_TRANSMIT) ( + IN struct _EFI_UDP4 *This, + IN EFI_UDP4_COMPLETION_TOKEN *Token + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_UDP4_RECEIVE) ( + IN struct _EFI_UDP4 *This, + IN EFI_UDP4_COMPLETION_TOKEN *Token + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_UDP4_CANCEL)( + IN struct _EFI_UDP4 *This, + IN EFI_UDP4_COMPLETION_TOKEN *Token OPTIONAL + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_UDP4_POLL) ( + IN struct _EFI_UDP4 *This + ); + +typedef struct _EFI_UDP4 { + EFI_UDP4_GET_MODE_DATA GetModeData; + EFI_UDP4_CONFIGURE Configure; + EFI_UDP4_GROUPS Groups; + EFI_UDP4_ROUTES Routes; + EFI_UDP4_TRANSMIT Transmit; + EFI_UDP4_RECEIVE Receive; + EFI_UDP4_CANCEL Cancel; + EFI_UDP4_POLL Poll; +} EFI_UDP4; + +typedef struct { + BOOLEAN AcceptPromiscuous; + BOOLEAN AcceptAnyPort; + BOOLEAN AllowDuplicatePort; + UINT8 TrafficClass; + UINT8 HopLimit; + UINT32 ReceiveTimeout; + UINT32 TransmitTimeout; + EFI_IPv6_ADDRESS StationAddress; + UINT16 StationPort; + EFI_IPv6_ADDRESS RemoteAddress; + UINT16 RemotePort; +} EFI_UDP6_CONFIG_DATA; + +typedef +EFI_STATUS +(EFIAPI *EFI_UDP6_GET_MODE_DATA) ( + IN struct _EFI_UDP6 *This, + OUT EFI_UDP6_CONFIG_DATA *Udp6ConfigData OPTIONAL, + OUT EFI_IP6_MODE_DATA *Ip6ModeData OPTIONAL, + OUT EFI_MANAGED_NETWORK_CONFIG_DATA *MnpConfigData OPTIONAL, + OUT EFI_SIMPLE_NETWORK_MODE *SnpModeData OPTIONAL + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_UDP6_CONFIGURE) ( + IN struct _EFI_UDP6 *This, + IN EFI_UDP6_CONFIG_DATA *UdpConfigData OPTIONAL + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_UDP6_GROUPS) ( + IN struct _EFI_UDP6 *This, + IN BOOLEAN JoinFlag, + IN EFI_IPv6_ADDRESS *MulticastAddress OPTIONAL + ); + +typedef struct { + EFI_IPv6_ADDRESS SourceAddress; + UINT16 SourcePort; + EFI_IPv6_ADDRESS DestinationAddress; + UINT16 DestinationPort; +} EFI_UDP6_SESSION_DATA; + +typedef struct { + UINT32 FragmentLength; + VOID *FragmentBuffer; +} EFI_UDP6_FRAGMENT_DATA; + +typedef struct { + EFI_TIME TimeStamp; + EFI_EVENT RecycleSignal; + EFI_UDP6_SESSION_DATA UdpSession; + UINT32 DataLength; + UINT32 FragmentCount; + EFI_UDP6_FRAGMENT_DATA FragmentTable[1]; +} EFI_UDP6_RECEIVE_DATA; + +typedef struct { + EFI_UDP6_SESSION_DATA *UdpSessionData; + UINT32 DataLength; + UINT32 FragmentCount; + EFI_UDP6_FRAGMENT_DATA FragmentTable[1]; +} EFI_UDP6_TRANSMIT_DATA; + +typedef struct { + EFI_EVENT Event; + EFI_STATUS Status; + union { + EFI_UDP6_RECEIVE_DATA *RxData; + EFI_UDP6_TRANSMIT_DATA *TxData; + } Packet; +} EFI_UDP6_COMPLETION_TOKEN; + +typedef +EFI_STATUS +(EFIAPI *EFI_UDP6_TRANSMIT) ( + IN struct _EFI_UDP6 *This, + IN EFI_UDP6_COMPLETION_TOKEN *Token + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_UDP6_RECEIVE) ( + IN struct _EFI_UDP6 *This, + IN EFI_UDP6_COMPLETION_TOKEN *Token + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_UDP6_CANCEL)( + IN struct _EFI_UDP6 *This, + IN EFI_UDP6_COMPLETION_TOKEN *Token OPTIONAL + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_UDP6_POLL) ( + IN struct _EFI_UDP6 *This + ); + +typedef struct _EFI_UDP6 { + EFI_UDP6_GET_MODE_DATA GetModeData; + EFI_UDP6_CONFIGURE Configure; + EFI_UDP6_GROUPS Groups; + EFI_UDP6_TRANSMIT Transmit; + EFI_UDP6_RECEIVE Receive; + EFI_UDP6_CANCEL Cancel; + EFI_UDP6_POLL Poll; +} EFI_UDP6; + +#endif /* _EFI_UDP_H */ diff --git a/gnu-efi/inc/efiui.h b/gnu-efi/inc/efiui.h new file mode 100644 index 0000000..3756936 --- /dev/null +++ b/gnu-efi/inc/efiui.h @@ -0,0 +1,58 @@ +#ifndef _EFI_UI_H +#define _EFI_UI_H + +/*++ + +Copyright (c) 200 Intel Corporation + +Module Name: + + EfiUi.h + +Abstract: + Protocol used to build User Interface (UI) stuff. + + This protocol is just data. It is a multi dimentional array. + For each string there is an array of UI_STRING_ENTRY. Each string + is for a different language translation of the same string. The list + is terminated by a NULL UiString. There can be any number of + UI_STRING_ENTRY arrays. A NULL array terminates the list. A NULL array + entry contains all zeros. + + Thus the shortest possible EFI_UI_PROTOCOL has three UI_STRING_ENTRY. + The String, it's NULL terminator, and the NULL terminator for the entire + thing. + + +Revision History + +--*/ + +#define EFI_UI_INTERFACE_PROTOCOL_GUID \ + { 0x32dd7981, 0x2d27, 0x11d4, {0xbc, 0x8b, 0x0, 0x80, 0xc7, 0x3c, 0x88, 0x81} } +#define EFI_UI_PROTOCOL EFI_UI_INTERFACE_PROTOCOL_GUID + + +typedef enum { + UiDeviceString, + UiVendorString, + UiMaxString +} UI_STRING_TYPE; + +typedef struct { + ISO_639_2 *LangCode; + CHAR16 *UiString; +} UI_STRING_ENTRY; + +#define EFI_UI_INTERFACE_PROTOCOL_VERSION 0x00010000 +#define EFI_UI_VERSION EFI_UI_INTERFACE_PROTOCOL_VERSION + +typedef struct _EFI_UI_INTERFACE_PROTOCOL { + UINT32 Version; + UI_STRING_ENTRY *Entry; +} EFI_UI_INTERFACE_PROTOCOL; + +typedef struct _EFI_UI_INTERFACE_PROTOCOL _UI_INTERFACE; +typedef EFI_UI_INTERFACE_PROTOCOL UI_INTERFACE; + +#endif diff --git a/gnu-efi/inc/ia32/efibind.h b/gnu-efi/inc/ia32/efibind.h new file mode 100644 index 0000000..27459e4 --- /dev/null +++ b/gnu-efi/inc/ia32/efibind.h @@ -0,0 +1,291 @@ +/*++ + +Copyright (c) 1998 Intel Corporation + +Module Name: + + efefind.h + +Abstract: + + EFI to compile bindings + + + + +Revision History + +--*/ + +#ifndef __GNUC__ +#pragma pack() +#endif + +// +// Basic int types of various widths +// + +#if !defined(__STDC_VERSION__) || (__STDC_VERSION__ < 199901L ) && !defined(__cplusplus) + + // No ANSI C 1999/2000 stdint.h integer width declarations + + #if defined(_MSC_EXTENSIONS) + + // Use Microsoft C compiler integer width declarations + + typedef unsigned __int64 uint64_t; + typedef __int64 int64_t; + typedef unsigned __int32 uint32_t; + typedef __int32 int32_t; + typedef unsigned short uint16_t; + typedef short int16_t; + typedef unsigned char uint8_t; + typedef char int8_t; + #elif defined(__GNUC__) + typedef int __attribute__((__mode__(__DI__))) int64_t; + typedef unsigned int __attribute__((__mode__(__DI__))) uint64_t; + typedef unsigned int uint32_t; + typedef int int32_t; + typedef unsigned short uint16_t; + typedef short int16_t; + typedef unsigned char uint8_t; + typedef signed char int8_t; + #elif defined(UNIX_LP64) + + /* Use LP64 programming model from C_FLAGS for integer width declarations */ + + typedef unsigned long uint64_t; + typedef long int64_t; + typedef unsigned int uint32_t; + typedef int int32_t; + typedef unsigned short uint16_t; + typedef short int16_t; + typedef unsigned char uint8_t; + typedef char int8_t; + #else + + /* Assume P64 programming model from C_FLAGS for integer width declarations */ + + typedef unsigned long long uint64_t __attribute__((aligned (8))); + typedef long long int64_t __attribute__((aligned (8))); + typedef unsigned int uint32_t; + typedef int int32_t; + typedef unsigned short uint16_t; + typedef short int16_t; + typedef unsigned char uint8_t; + typedef char int8_t; + #endif + typedef uint32_t uintptr_t; + typedef int32_t intptr_t; +#elif defined(__GNUC__) + #include +#endif + +// +// Basic EFI types of various widths +// + +#ifndef __WCHAR_TYPE__ +# define __WCHAR_TYPE__ short +#endif + +typedef uint64_t UINT64; +typedef int64_t INT64; + +#ifndef _BASETSD_H_ + typedef uint32_t UINT32; + typedef int32_t INT32; +#endif + +typedef uint16_t UINT16; +typedef int16_t INT16; +typedef uint8_t UINT8; +typedef int8_t INT8; +typedef __WCHAR_TYPE__ WCHAR; + +#undef VOID +#define VOID void + + +typedef int32_t INTN; +typedef uint32_t UINTN; + +#ifdef EFI_NT_EMULATOR + #define POST_CODE(_Data) +#else + #ifdef EFI_DEBUG +#define POST_CODE(_Data) __asm mov eax,(_Data) __asm out 0x80,al + #else + #define POST_CODE(_Data) + #endif +#endif + +#define EFIERR(a) (0x80000000 | a) +#define EFI_ERROR_MASK 0x80000000 +#define EFIERR_OEM(a) (0xc0000000 | a) + + +#define BAD_POINTER 0xFBFBFBFB +#define MAX_ADDRESS 0xFFFFFFFF + +#ifdef EFI_NT_EMULATOR + #define BREAKPOINT() __asm { int 3 } +#else + #define BREAKPOINT() while (TRUE); // Make it hang on Bios[Dbg]32 +#endif + +// +// Pointers must be aligned to these address to function +// + +#define MIN_ALIGNMENT_SIZE 4 + +#define ALIGN_VARIABLE(Value ,Adjustment) \ + (UINTN)Adjustment = 0; \ + if((UINTN)Value % MIN_ALIGNMENT_SIZE) \ + (UINTN)Adjustment = MIN_ALIGNMENT_SIZE - ((UINTN)Value % MIN_ALIGNMENT_SIZE); \ + Value = (UINTN)Value + (UINTN)Adjustment + + +// +// Define macros to build data structure signatures from characters. +// + +#define EFI_SIGNATURE_16(A,B) ((A) | (B<<8)) +#define EFI_SIGNATURE_32(A,B,C,D) (EFI_SIGNATURE_16(A,B) | (EFI_SIGNATURE_16(C,D) << 16)) +#define EFI_SIGNATURE_64(A,B,C,D,E,F,G,H) (EFI_SIGNATURE_32(A,B,C,D) | ((UINT64)(EFI_SIGNATURE_32(E,F,G,H)) << 32)) +// +// To export & import functions in the EFI emulator environment +// + +#ifdef EFI_NT_EMULATOR + #define EXPORTAPI __declspec( dllexport ) +#else + #define EXPORTAPI +#endif + + +// +// EFIAPI - prototype calling convention for EFI function pointers +// BOOTSERVICE - prototype for implementation of a boot service interface +// RUNTIMESERVICE - prototype for implementation of a runtime service interface +// RUNTIMEFUNCTION - prototype for implementation of a runtime function that is not a service +// RUNTIME_CODE - pragma macro for declaring runtime code +// + +#ifndef EFIAPI // Forces EFI calling conventions reguardless of compiler options + #ifdef _MSC_EXTENSIONS + #define EFIAPI __cdecl // Force C calling convention for Microsoft C compiler + #else + #define EFIAPI // Substitute expresion to force C calling convention + #endif +#endif + +#define BOOTSERVICE +//#define RUNTIMESERVICE(proto,a) alloc_text("rtcode",a); proto a +//#define RUNTIMEFUNCTION(proto,a) alloc_text("rtcode",a); proto a +#define RUNTIMESERVICE +#define RUNTIMEFUNCTION + + +#define RUNTIME_CODE(a) alloc_text("rtcode", a) +#define BEGIN_RUNTIME_DATA() data_seg("rtdata") +#define END_RUNTIME_DATA() data_seg("") + +#define VOLATILE volatile + +#define MEMORY_FENCE() + +#ifdef EFI_NT_EMULATOR + +// +// To help ensure proper coding of integrated drivers, they are +// compiled as DLLs. In NT they require a dll init entry pointer. +// The macro puts a stub entry point into the DLL so it will load. +// + +#define EFI_DRIVER_ENTRY_POINT(InitFunction) \ + UINTN \ + __stdcall \ + _DllMainCRTStartup ( \ + UINTN Inst, \ + UINTN reason_for_call, \ + VOID *rserved \ + ) \ + { \ + return 1; \ + } \ + \ + int \ + EXPORTAPI \ + __cdecl \ + InitializeDriver ( \ + void *ImageHandle, \ + void *SystemTable \ + ) \ + { \ + return InitFunction(ImageHandle, SystemTable); \ + } + + + #define LOAD_INTERNAL_DRIVER(_if, type, name, entry) \ + (_if)->LoadInternal(type, name, NULL) + +#else // EFI_NT_EMULATOR + +// +// When build similiar to FW, then link everything together as +// one big module. For the MSVC toolchain, we simply tell the +// linker what our driver init function is using /ENTRY. +// +#if defined(_MSC_EXTENSIONS) + #define EFI_DRIVER_ENTRY_POINT(InitFunction) \ + __pragma(comment(linker, "/ENTRY:" # InitFunction)) +#else + #define EFI_DRIVER_ENTRY_POINT(InitFunction) \ + UINTN \ + InitializeDriver ( \ + VOID *ImageHandle, \ + VOID *SystemTable \ + ) \ + { \ + return InitFunction(ImageHandle, \ + SystemTable); \ + } \ + \ + EFI_STATUS efi_main( \ + EFI_HANDLE image, \ + EFI_SYSTEM_TABLE *systab \ + ) __attribute__((weak, \ + alias ("InitializeDriver"))); +#endif + + #define LOAD_INTERNAL_DRIVER(_if, type, name, entry) \ + (_if)->LoadInternal(type, name, entry) + +#endif // EFI_FW_NT + +// +// Some compilers don't support the forward reference construct: +// typedef struct XXXXX +// +// The following macro provide a workaround for such cases. +// +#ifdef NO_INTERFACE_DECL +#define INTERFACE_DECL(x) +#else +#if defined(__GNUC__) || defined(_MSC_EXTENSIONS) +#define INTERFACE_DECL(x) struct x +#else +#define INTERFACE_DECL(x) typedef struct x +#endif +#endif + +/* No efi call wrapper for IA32 architecture */ +#define uefi_call_wrapper(func, va_num, ...) func(__VA_ARGS__) +#define EFI_FUNCTION + +#ifdef _MSC_EXTENSIONS +#pragma warning ( disable : 4731 ) // Suppress warnings about modification of EBP +#endif + diff --git a/gnu-efi/inc/ia32/efilibplat.h b/gnu-efi/inc/ia32/efilibplat.h new file mode 100644 index 0000000..3844578 --- /dev/null +++ b/gnu-efi/inc/ia32/efilibplat.h @@ -0,0 +1,26 @@ +/*++ + +Copyright (c) 1998 Intel Corporation + +Module Name: + + efilibplat.h + +Abstract: + + EFI to compile bindings + + + + +Revision History + +--*/ + +VOID +InitializeLibPlatform ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + + diff --git a/gnu-efi/inc/ia32/efisetjmp_arch.h b/gnu-efi/inc/ia32/efisetjmp_arch.h new file mode 100644 index 0000000..a5c1a81 --- /dev/null +++ b/gnu-efi/inc/ia32/efisetjmp_arch.h @@ -0,0 +1,15 @@ +#ifndef GNU_EFI_IA32_SETJMP_H +#define GNU_EFI_IA32_SETJMP_H + +#define JMPBUF_ALIGN 4 + +typedef struct { + UINT32 Ebx; + UINT32 Esi; + UINT32 Edi; + UINT32 Ebp; + UINT32 Esp; + UINT32 Eip; +} ALIGN(JMPBUF_ALIGN) jmp_buf[1]; + +#endif /* GNU_EFI_IA32_SETJMP_H */ diff --git a/gnu-efi/inc/ia32/pe.h b/gnu-efi/inc/ia32/pe.h new file mode 100644 index 0000000..979b936 --- /dev/null +++ b/gnu-efi/inc/ia32/pe.h @@ -0,0 +1,595 @@ +/* + PE32+ header file + */ +#ifndef _PE_H +#define _PE_H + +#define IMAGE_DOS_SIGNATURE 0x5A4D // MZ +#define IMAGE_OS2_SIGNATURE 0x454E // NE +#define IMAGE_OS2_SIGNATURE_LE 0x454C // LE +#define IMAGE_NT_SIGNATURE 0x00004550 // PE00 +#define IMAGE_EDOS_SIGNATURE 0x44454550 // PEED + + +typedef struct _IMAGE_DOS_HEADER { // DOS .EXE header + UINT16 e_magic; // Magic number + UINT16 e_cblp; // Bytes on last page of file + UINT16 e_cp; // Pages in file + UINT16 e_crlc; // Relocations + UINT16 e_cparhdr; // Size of header in paragraphs + UINT16 e_minalloc; // Minimum extra paragraphs needed + UINT16 e_maxalloc; // Maximum extra paragraphs needed + UINT16 e_ss; // Initial (relative) SS value + UINT16 e_sp; // Initial SP value + UINT16 e_csum; // Checksum + UINT16 e_ip; // Initial IP value + UINT16 e_cs; // Initial (relative) CS value + UINT16 e_lfarlc; // File address of relocation table + UINT16 e_ovno; // Overlay number + UINT16 e_res[4]; // Reserved words + UINT16 e_oemid; // OEM identifier (for e_oeminfo) + UINT16 e_oeminfo; // OEM information; e_oemid specific + UINT16 e_res2[10]; // Reserved words + UINT32 e_lfanew; // File address of new exe header + } IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER; + +typedef struct _IMAGE_OS2_HEADER { // OS/2 .EXE header + UINT16 ne_magic; // Magic number + UINT8 ne_ver; // Version number + UINT8 ne_rev; // Revision number + UINT16 ne_enttab; // Offset of Entry Table + UINT16 ne_cbenttab; // Number of bytes in Entry Table + UINT32 ne_crc; // Checksum of whole file + UINT16 ne_flags; // Flag UINT16 + UINT16 ne_autodata; // Automatic data segment number + UINT16 ne_heap; // Initial heap allocation + UINT16 ne_stack; // Initial stack allocation + UINT32 ne_csip; // Initial CS:IP setting + UINT32 ne_sssp; // Initial SS:SP setting + UINT16 ne_cseg; // Count of file segments + UINT16 ne_cmod; // Entries in Module Reference Table + UINT16 ne_cbnrestab; // Size of non-resident name table + UINT16 ne_segtab; // Offset of Segment Table + UINT16 ne_rsrctab; // Offset of Resource Table + UINT16 ne_restab; // Offset of resident name table + UINT16 ne_modtab; // Offset of Module Reference Table + UINT16 ne_imptab; // Offset of Imported Names Table + UINT32 ne_nrestab; // Offset of Non-resident Names Table + UINT16 ne_cmovent; // Count of movable entries + UINT16 ne_align; // Segment alignment shift count + UINT16 ne_cres; // Count of resource segments + UINT8 ne_exetyp; // Target Operating system + UINT8 ne_flagsothers; // Other .EXE flags + UINT16 ne_pretthunks; // offset to return thunks + UINT16 ne_psegrefbytes; // offset to segment ref. bytes + UINT16 ne_swaparea; // Minimum code swap area size + UINT16 ne_expver; // Expected Windows version number + } IMAGE_OS2_HEADER, *PIMAGE_OS2_HEADER; + +// +// File header format. +// + +typedef struct _IMAGE_FILE_HEADER { + UINT16 Machine; + UINT16 NumberOfSections; + UINT32 TimeDateStamp; + UINT32 PointerToSymbolTable; + UINT32 NumberOfSymbols; + UINT16 SizeOfOptionalHeader; + UINT16 Characteristics; +} IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER; + +#define IMAGE_SIZEOF_FILE_HEADER 20 + +#define IMAGE_FILE_RELOCS_STRIPPED 0x0001 // Relocation info stripped from file. +#define IMAGE_FILE_EXECUTABLE_IMAGE 0x0002 // File is executable (i.e. no unresolved externel references). +#define IMAGE_FILE_LINE_NUMS_STRIPPED 0x0004 // Line nunbers stripped from file. +#define IMAGE_FILE_LOCAL_SYMS_STRIPPED 0x0008 // Local symbols stripped from file. +#define IMAGE_FILE_BYTES_REVERSED_LO 0x0080 // Bytes of machine word are reversed. +#define IMAGE_FILE_32BIT_MACHINE 0x0100 // 32 bit word machine. +#define IMAGE_FILE_DEBUG_STRIPPED 0x0200 // Debugging info stripped from file in .DBG file +#define IMAGE_FILE_SYSTEM 0x1000 // System File. +#define IMAGE_FILE_DLL 0x2000 // File is a DLL. +#define IMAGE_FILE_BYTES_REVERSED_HI 0x8000 // Bytes of machine word are reversed. + +#define IMAGE_FILE_MACHINE_UNKNOWN 0 +#define IMAGE_FILE_MACHINE_I386 0x14c // Intel 386. +#define IMAGE_FILE_MACHINE_R3000 0x162 // MIPS little-endian, 0540 big-endian +#define IMAGE_FILE_MACHINE_R4000 0x166 // MIPS little-endian +#define IMAGE_FILE_MACHINE_ALPHA 0x184 // Alpha_AXP +#define IMAGE_FILE_MACHINE_ARMTHUMB_MIXED 0x1c2 // Arm/Thumb +#define IMAGE_FILE_MACHINE_POWERPC 0x1F0 // IBM PowerPC Little-Endian +#define IMAGE_FILE_MACHINE_IA64 0x200 // IA-64 +#define IMAGE_FILE_MACHINE_TAHOE 0x7cc // Intel EM machine +#define IMAGE_FILE_MACHINE_EBC 0xebc // EFI Byte Code +#define IMAGE_FILE_MACHINE_X64 0x8664 // x86_64 +// +// Directory format. +// + +typedef struct _IMAGE_DATA_DIRECTORY { + UINT32 VirtualAddress; + UINT32 Size; +} IMAGE_DATA_DIRECTORY, *PIMAGE_DATA_DIRECTORY; + +#define IMAGE_NUMBEROF_DIRECTORY_ENTRIES 16 + +// +// Optional header format. +// + +typedef struct _IMAGE_OPTIONAL_HEADER { + // + // Standard fields. + // + + UINT16 Magic; + UINT8 MajorLinkerVersion; + UINT8 MinorLinkerVersion; + UINT32 SizeOfCode; + UINT32 SizeOfInitializedData; + UINT32 SizeOfUninitializedData; + UINT32 AddressOfEntryPoint; + UINT32 BaseOfCode; + UINT32 BaseOfData; + + // + // NT additional fields. + // + + UINT32 ImageBase; + UINT32 SectionAlignment; + UINT32 FileAlignment; + UINT16 MajorOperatingSystemVersion; + UINT16 MinorOperatingSystemVersion; + UINT16 MajorImageVersion; + UINT16 MinorImageVersion; + UINT16 MajorSubsystemVersion; + UINT16 MinorSubsystemVersion; + UINT32 Reserved1; + UINT32 SizeOfImage; + UINT32 SizeOfHeaders; + UINT32 CheckSum; + UINT16 Subsystem; + UINT16 DllCharacteristics; + UINT32 SizeOfStackReserve; + UINT32 SizeOfStackCommit; + UINT32 SizeOfHeapReserve; + UINT32 SizeOfHeapCommit; + UINT32 LoaderFlags; + UINT32 NumberOfRvaAndSizes; + IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES]; +} IMAGE_OPTIONAL_HEADER, *PIMAGE_OPTIONAL_HEADER; + +typedef struct _IMAGE_ROM_OPTIONAL_HEADER { + UINT16 Magic; + UINT8 MajorLinkerVersion; + UINT8 MinorLinkerVersion; + UINT32 SizeOfCode; + UINT32 SizeOfInitializedData; + UINT32 SizeOfUninitializedData; + UINT32 AddressOfEntryPoint; + UINT32 BaseOfCode; + UINT32 BaseOfData; + UINT32 BaseOfBss; + UINT32 GprMask; + UINT32 CprMask[4]; + UINT32 GpValue; +} IMAGE_ROM_OPTIONAL_HEADER, *PIMAGE_ROM_OPTIONAL_HEADER; + +#define IMAGE_SIZEOF_ROM_OPTIONAL_HEADER 56 +#define IMAGE_SIZEOF_STD_OPTIONAL_HEADER 28 +#define IMAGE_SIZEOF_NT_OPTIONAL_HEADER 224 + +#define IMAGE_NT_OPTIONAL_HDR_MAGIC 0x10b +#define IMAGE_ROM_OPTIONAL_HDR_MAGIC 0x107 + +typedef struct _IMAGE_NT_HEADERS { + UINT32 Signature; + IMAGE_FILE_HEADER FileHeader; + IMAGE_OPTIONAL_HEADER OptionalHeader; +} IMAGE_NT_HEADERS, *PIMAGE_NT_HEADERS; + +typedef struct _IMAGE_ROM_HEADERS { + IMAGE_FILE_HEADER FileHeader; + IMAGE_ROM_OPTIONAL_HEADER OptionalHeader; +} IMAGE_ROM_HEADERS, *PIMAGE_ROM_HEADERS; + +#define IMAGE_FIRST_SECTION( ntheader ) ((PIMAGE_SECTION_HEADER) \ + ((UINT32)ntheader + \ + FIELD_OFFSET( IMAGE_NT_HEADERS, OptionalHeader ) + \ + ((PIMAGE_NT_HEADERS)(ntheader))->FileHeader.SizeOfOptionalHeader \ + )) + + +// Subsystem Values + +#define IMAGE_SUBSYSTEM_UNKNOWN 0 // Unknown subsystem. +#define IMAGE_SUBSYSTEM_NATIVE 1 // Image doesn't require a subsystem. +#define IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem. +#define IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem. +#define IMAGE_SUBSYSTEM_OS2_CUI 5 // image runs in the OS/2 character subsystem. +#define IMAGE_SUBSYSTEM_POSIX_CUI 7 // image run in the Posix character subsystem. + + +// Directory Entries + +#define IMAGE_DIRECTORY_ENTRY_EXPORT 0 // Export Directory +#define IMAGE_DIRECTORY_ENTRY_IMPORT 1 // Import Directory +#define IMAGE_DIRECTORY_ENTRY_RESOURCE 2 // Resource Directory +#define IMAGE_DIRECTORY_ENTRY_EXCEPTION 3 // Exception Directory +#define IMAGE_DIRECTORY_ENTRY_SECURITY 4 // Security Directory +#define IMAGE_DIRECTORY_ENTRY_BASERELOC 5 // Base Relocation Table +#define IMAGE_DIRECTORY_ENTRY_DEBUG 6 // Debug Directory +#define IMAGE_DIRECTORY_ENTRY_COPYRIGHT 7 // Description String +#define IMAGE_DIRECTORY_ENTRY_GLOBALPTR 8 // Machine Value (MIPS GP) +#define IMAGE_DIRECTORY_ENTRY_TLS 9 // TLS Directory +#define IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG 10 // Load Configuration Directory + +// +// Section header format. +// + +#define IMAGE_SIZEOF_SHORT_NAME 8 + +typedef struct _IMAGE_SECTION_HEADER { + UINT8 Name[IMAGE_SIZEOF_SHORT_NAME]; + union { + UINT32 PhysicalAddress; + UINT32 VirtualSize; + } Misc; + UINT32 VirtualAddress; + UINT32 SizeOfRawData; + UINT32 PointerToRawData; + UINT32 PointerToRelocations; + UINT32 PointerToLinenumbers; + UINT16 NumberOfRelocations; + UINT16 NumberOfLinenumbers; + UINT32 Characteristics; +} IMAGE_SECTION_HEADER, *PIMAGE_SECTION_HEADER; + +#define IMAGE_SIZEOF_SECTION_HEADER 40 + +#define IMAGE_SCN_TYPE_NO_PAD 0x00000008 // Reserved. + +#define IMAGE_SCN_CNT_CODE 0x00000020 // Section contains code. +#define IMAGE_SCN_CNT_INITIALIZED_DATA 0x00000040 // Section contains initialized data. +#define IMAGE_SCN_CNT_UNINITIALIZED_DATA 0x00000080 // Section contains uninitialized data. + +#define IMAGE_SCN_LNK_OTHER 0x00000100 // Reserved. +#define IMAGE_SCN_LNK_INFO 0x00000200 // Section contains comments or some other type of information. +#define IMAGE_SCN_LNK_REMOVE 0x00000800 // Section contents will not become part of image. +#define IMAGE_SCN_LNK_COMDAT 0x00001000 // Section contents comdat. + +#define IMAGE_SCN_ALIGN_1BYTES 0x00100000 // +#define IMAGE_SCN_ALIGN_2BYTES 0x00200000 // +#define IMAGE_SCN_ALIGN_4BYTES 0x00300000 // +#define IMAGE_SCN_ALIGN_8BYTES 0x00400000 // +#define IMAGE_SCN_ALIGN_16BYTES 0x00500000 // Default alignment if no others are specified. +#define IMAGE_SCN_ALIGN_32BYTES 0x00600000 // +#define IMAGE_SCN_ALIGN_64BYTES 0x00700000 // + +#define IMAGE_SCN_MEM_DISCARDABLE 0x02000000 // Section can be discarded. +#define IMAGE_SCN_MEM_NOT_CACHED 0x04000000 // Section is not cachable. +#define IMAGE_SCN_MEM_NOT_PAGED 0x08000000 // Section is not pageable. +#define IMAGE_SCN_MEM_SHARED 0x10000000 // Section is shareable. +#define IMAGE_SCN_MEM_EXECUTE 0x20000000 // Section is executable. +#define IMAGE_SCN_MEM_READ 0x40000000 // Section is readable. +#define IMAGE_SCN_MEM_WRITE 0x80000000 // Section is writeable. + +// +// Symbol format. +// + + +#define IMAGE_SIZEOF_SYMBOL 18 + +// +// Section values. +// +// Symbols have a section number of the section in which they are +// defined. Otherwise, section numbers have the following meanings: +// + +#define IMAGE_SYM_UNDEFINED (UINT16)0 // Symbol is undefined or is common. +#define IMAGE_SYM_ABSOLUTE (UINT16)-1 // Symbol is an absolute value. +#define IMAGE_SYM_DEBUG (UINT16)-2 // Symbol is a special debug item. + +// +// Type (fundamental) values. +// + +#define IMAGE_SYM_TYPE_NULL 0 // no type. +#define IMAGE_SYM_TYPE_VOID 1 // +#define IMAGE_SYM_TYPE_CHAR 2 // type character. +#define IMAGE_SYM_TYPE_SHORT 3 // type short integer. +#define IMAGE_SYM_TYPE_INT 4 // +#define IMAGE_SYM_TYPE_LONG 5 // +#define IMAGE_SYM_TYPE_FLOAT 6 // +#define IMAGE_SYM_TYPE_DOUBLE 7 // +#define IMAGE_SYM_TYPE_STRUCT 8 // +#define IMAGE_SYM_TYPE_UNION 9 // +#define IMAGE_SYM_TYPE_ENUM 10 // enumeration. +#define IMAGE_SYM_TYPE_MOE 11 // member of enumeration. +#define IMAGE_SYM_TYPE_BYTE 12 // +#define IMAGE_SYM_TYPE_WORD 13 // +#define IMAGE_SYM_TYPE_UINT 14 // +#define IMAGE_SYM_TYPE_DWORD 15 // + +// +// Type (derived) values. +// + +#define IMAGE_SYM_DTYPE_NULL 0 // no derived type. +#define IMAGE_SYM_DTYPE_POINTER 1 // pointer. +#define IMAGE_SYM_DTYPE_FUNCTION 2 // function. +#define IMAGE_SYM_DTYPE_ARRAY 3 // array. + +// +// Storage classes. +// + +#define IMAGE_SYM_CLASS_END_OF_FUNCTION (BYTE )-1 +#define IMAGE_SYM_CLASS_NULL 0 +#define IMAGE_SYM_CLASS_AUTOMATIC 1 +#define IMAGE_SYM_CLASS_EXTERNAL 2 +#define IMAGE_SYM_CLASS_STATIC 3 +#define IMAGE_SYM_CLASS_REGISTER 4 +#define IMAGE_SYM_CLASS_EXTERNAL_DEF 5 +#define IMAGE_SYM_CLASS_LABEL 6 +#define IMAGE_SYM_CLASS_UNDEFINED_LABEL 7 +#define IMAGE_SYM_CLASS_MEMBER_OF_STRUCT 8 +#define IMAGE_SYM_CLASS_ARGUMENT 9 +#define IMAGE_SYM_CLASS_STRUCT_TAG 10 +#define IMAGE_SYM_CLASS_MEMBER_OF_UNION 11 +#define IMAGE_SYM_CLASS_UNION_TAG 12 +#define IMAGE_SYM_CLASS_TYPE_DEFINITION 13 +#define IMAGE_SYM_CLASS_UNDEFINED_STATIC 14 +#define IMAGE_SYM_CLASS_ENUM_TAG 15 +#define IMAGE_SYM_CLASS_MEMBER_OF_ENUM 16 +#define IMAGE_SYM_CLASS_REGISTER_PARAM 17 +#define IMAGE_SYM_CLASS_BIT_FIELD 18 +#define IMAGE_SYM_CLASS_BLOCK 100 +#define IMAGE_SYM_CLASS_FUNCTION 101 +#define IMAGE_SYM_CLASS_END_OF_STRUCT 102 +#define IMAGE_SYM_CLASS_FILE 103 +// new +#define IMAGE_SYM_CLASS_SECTION 104 +#define IMAGE_SYM_CLASS_WEAK_EXTERNAL 105 + +// type packing constants + +#define N_BTMASK 017 +#define N_TMASK 060 +#define N_TMASK1 0300 +#define N_TMASK2 0360 +#define N_BTSHFT 4 +#define N_TSHIFT 2 + +// MACROS + +// +// Communal selection types. +// + +#define IMAGE_COMDAT_SELECT_NODUPLICATES 1 +#define IMAGE_COMDAT_SELECT_ANY 2 +#define IMAGE_COMDAT_SELECT_SAME_SIZE 3 +#define IMAGE_COMDAT_SELECT_EXACT_MATCH 4 +#define IMAGE_COMDAT_SELECT_ASSOCIATIVE 5 + +#define IMAGE_WEAK_EXTERN_SEARCH_NOLIBRARY 1 +#define IMAGE_WEAK_EXTERN_SEARCH_LIBRARY 2 +#define IMAGE_WEAK_EXTERN_SEARCH_ALIAS 3 + + +// +// Relocation format. +// + +typedef struct _IMAGE_RELOCATION { + UINT32 VirtualAddress; + UINT32 SymbolTableIndex; + UINT16 Type; +} IMAGE_RELOCATION; + +#define IMAGE_SIZEOF_RELOCATION 10 + +// +// I386 relocation types. +// + +#define IMAGE_REL_I386_ABSOLUTE 0 // Reference is absolute, no relocation is necessary +#define IMAGE_REL_I386_DIR16 01 // Direct 16-bit reference to the symbols virtual address +#define IMAGE_REL_I386_REL16 02 // PC-relative 16-bit reference to the symbols virtual address +#define IMAGE_REL_I386_DIR32 06 // Direct 32-bit reference to the symbols virtual address +#define IMAGE_REL_I386_DIR32NB 07 // Direct 32-bit reference to the symbols virtual address, base not included +#define IMAGE_REL_I386_SEG12 011 // Direct 16-bit reference to the segment-selector bits of a 32-bit virtual address +#define IMAGE_REL_I386_SECTION 012 +#define IMAGE_REL_I386_SECREL 013 +#define IMAGE_REL_I386_REL32 024 // PC-relative 32-bit reference to the symbols virtual address + +// +// MIPS relocation types. +// + +#define IMAGE_REL_MIPS_ABSOLUTE 0 // Reference is absolute, no relocation is necessary +#define IMAGE_REL_MIPS_REFHALF 01 +#define IMAGE_REL_MIPS_REFWORD 02 +#define IMAGE_REL_MIPS_JMPADDR 03 +#define IMAGE_REL_MIPS_REFHI 04 +#define IMAGE_REL_MIPS_REFLO 05 +#define IMAGE_REL_MIPS_GPREL 06 +#define IMAGE_REL_MIPS_LITERAL 07 +#define IMAGE_REL_MIPS_SECTION 012 +#define IMAGE_REL_MIPS_SECREL 013 +#define IMAGE_REL_MIPS_REFWORDNB 042 +#define IMAGE_REL_MIPS_PAIR 045 + +// +// Alpha Relocation types. +// + +#define IMAGE_REL_ALPHA_ABSOLUTE 0x0 +#define IMAGE_REL_ALPHA_REFLONG 0x1 +#define IMAGE_REL_ALPHA_REFQUAD 0x2 +#define IMAGE_REL_ALPHA_GPREL32 0x3 +#define IMAGE_REL_ALPHA_LITERAL 0x4 +#define IMAGE_REL_ALPHA_LITUSE 0x5 +#define IMAGE_REL_ALPHA_GPDISP 0x6 +#define IMAGE_REL_ALPHA_BRADDR 0x7 +#define IMAGE_REL_ALPHA_HINT 0x8 +#define IMAGE_REL_ALPHA_INLINE_REFLONG 0x9 +#define IMAGE_REL_ALPHA_REFHI 0xA +#define IMAGE_REL_ALPHA_REFLO 0xB +#define IMAGE_REL_ALPHA_PAIR 0xC +#define IMAGE_REL_ALPHA_MATCH 0xD +#define IMAGE_REL_ALPHA_SECTION 0xE +#define IMAGE_REL_ALPHA_SECREL 0xF +#define IMAGE_REL_ALPHA_REFLONGNB 0x10 + +// +// IBM PowerPC relocation types. +// + +#define IMAGE_REL_PPC_ABSOLUTE 0x0000 // NOP +#define IMAGE_REL_PPC_ADDR64 0x0001 // 64-bit address +#define IMAGE_REL_PPC_ADDR32 0x0002 // 32-bit address +#define IMAGE_REL_PPC_ADDR24 0x0003 // 26-bit address, shifted left 2 (branch absolute) +#define IMAGE_REL_PPC_ADDR16 0x0004 // 16-bit address +#define IMAGE_REL_PPC_ADDR14 0x0005 // 16-bit address, shifted left 2 (load doubleword) +#define IMAGE_REL_PPC_REL24 0x0006 // 26-bit PC-relative offset, shifted left 2 (branch relative) +#define IMAGE_REL_PPC_REL14 0x0007 // 16-bit PC-relative offset, shifted left 2 (br cond relative) +#define IMAGE_REL_PPC_TOCREL16 0x0008 // 16-bit offset from TOC base +#define IMAGE_REL_PPC_TOCREL14 0x0009 // 16-bit offset from TOC base, shifted left 2 (load doubleword) + +#define IMAGE_REL_PPC_ADDR32NB 0x000A // 32-bit addr w/o image base +#define IMAGE_REL_PPC_SECREL 0x000B // va of containing section (as in an image sectionhdr) +#define IMAGE_REL_PPC_SECTION 0x000C // sectionheader number +#define IMAGE_REL_PPC_IFGLUE 0x000D // substitute TOC restore instruction iff symbol is glue code +#define IMAGE_REL_PPC_IMGLUE 0x000E // symbol is glue code; virtual address is TOC restore instruction + +#define IMAGE_REL_PPC_TYPEMASK 0x00FF // mask to isolate above values in IMAGE_RELOCATION.Type + +// Flag bits in IMAGE_RELOCATION.TYPE + +#define IMAGE_REL_PPC_NEG 0x0100 // subtract reloc value rather than adding it +#define IMAGE_REL_PPC_BRTAKEN 0x0200 // fix branch prediction bit to predict branch taken +#define IMAGE_REL_PPC_BRNTAKEN 0x0400 // fix branch prediction bit to predict branch not taken +#define IMAGE_REL_PPC_TOCDEFN 0x0800 // toc slot defined in file (or, data in toc) + +// +// Based relocation format. +// + +typedef struct _IMAGE_BASE_RELOCATION { + UINT32 VirtualAddress; + UINT32 SizeOfBlock; +// UINT16 TypeOffset[1]; +} IMAGE_BASE_RELOCATION, *PIMAGE_BASE_RELOCATION; + +#define IMAGE_SIZEOF_BASE_RELOCATION 8 + +// +// Based relocation types. +// + +#define IMAGE_REL_BASED_ABSOLUTE 0 +#define IMAGE_REL_BASED_HIGH 1 +#define IMAGE_REL_BASED_LOW 2 +#define IMAGE_REL_BASED_HIGHLOW 3 +#define IMAGE_REL_BASED_HIGHADJ 4 +#define IMAGE_REL_BASED_MIPS_JMPADDR 5 +#define IMAGE_REL_BASED_IA64_IMM64 9 +#define IMAGE_REL_BASED_DIR64 10 + +// +// Line number format. +// + +typedef struct _IMAGE_LINENUMBER { + union { + UINT32 SymbolTableIndex; // Symbol table index of function name if Linenumber is 0. + UINT32 VirtualAddress; // Virtual address of line number. + } Type; + UINT16 Linenumber; // Line number. +} IMAGE_LINENUMBER; + +#define IMAGE_SIZEOF_LINENUMBER 6 + +// +// Archive format. +// + +#define IMAGE_ARCHIVE_START_SIZE 8 +#define IMAGE_ARCHIVE_START "!\n" +#define IMAGE_ARCHIVE_END "`\n" +#define IMAGE_ARCHIVE_PAD "\n" +#define IMAGE_ARCHIVE_LINKER_MEMBER "/ " +#define IMAGE_ARCHIVE_LONGNAMES_MEMBER "// " + +typedef struct _IMAGE_ARCHIVE_MEMBER_HEADER { + UINT8 Name[16]; // File member name - `/' terminated. + UINT8 Date[12]; // File member date - decimal. + UINT8 UserID[6]; // File member user id - decimal. + UINT8 GroupID[6]; // File member group id - decimal. + UINT8 Mode[8]; // File member mode - octal. + UINT8 Size[10]; // File member size - decimal. + UINT8 EndHeader[2]; // String to end header. +} IMAGE_ARCHIVE_MEMBER_HEADER, *PIMAGE_ARCHIVE_MEMBER_HEADER; + +#define IMAGE_SIZEOF_ARCHIVE_MEMBER_HDR 60 + +// +// DLL support. +// + +// +// Export Format +// + +typedef struct _IMAGE_EXPORT_DIRECTORY { + UINT32 Characteristics; + UINT32 TimeDateStamp; + UINT16 MajorVersion; + UINT16 MinorVersion; + UINT32 Name; + UINT32 Base; + UINT32 NumberOfFunctions; + UINT32 NumberOfNames; + UINT32 *AddressOfFunctions; + UINT32 *AddressOfNames; + UINT32 *AddressOfNameOrdinals; +} IMAGE_EXPORT_DIRECTORY, *PIMAGE_EXPORT_DIRECTORY; + +// +// Import Format +// + +typedef struct _IMAGE_IMPORT_BY_NAME { + UINT16 Hint; + UINT8 Name[1]; +} IMAGE_IMPORT_BY_NAME, *PIMAGE_IMPORT_BY_NAME; + +typedef struct _IMAGE_THUNK_DATA { + union { + UINT32 Function; + UINT32 Ordinal; + PIMAGE_IMPORT_BY_NAME AddressOfData; + } u1; +} IMAGE_THUNK_DATA, *PIMAGE_THUNK_DATA; + +#define IMAGE_ORDINAL_FLAG 0x80000000 +#define IMAGE_SNAP_BY_ORDINAL(Ordinal) ((Ordinal & IMAGE_ORDINAL_FLAG) != 0) +#define IMAGE_ORDINAL(Ordinal) (Ordinal & 0xffff) + +typedef struct _IMAGE_IMPORT_DESCRIPTOR { + UINT32 Characteristics; + UINT32 TimeDateStamp; + UINT32 ForwarderChain; + UINT32 Name; + PIMAGE_THUNK_DATA FirstThunk; +} IMAGE_IMPORT_DESCRIPTOR, *PIMAGE_IMPORT_DESCRIPTOR; + +#endif diff --git a/gnu-efi/inc/ia64/efibind.h b/gnu-efi/inc/ia64/efibind.h new file mode 100644 index 0000000..3ace8d5 --- /dev/null +++ b/gnu-efi/inc/ia64/efibind.h @@ -0,0 +1,233 @@ +/*++ + +Copyright (c) 1998 Intel Corporation + +Module Name: + + efefind.h + +Abstract: + + EFI to compile bindings + + + + +Revision History + +--*/ + +#pragma pack() + + +// +// Basic int types of various widths +// + +#if !defined(__STDC_VERSION__) || (__STDC_VERSION__ < 199901L ) && !defined(__cplusplus) + + // No ANSI C 1999/2000 stdint.h integer width declarations + + #ifdef _MSC_EXTENSIONS + // Use Microsoft C compiler integer width declarations + + typedef unsigned __int64 uint64_t; + typedef __int64 int64_t; + typedef unsigned __int32 uint32_t; + typedef __int32 int32_t; + typedef unsigned __int16 uint16_t; + typedef __int16 int16_t; + typedef unsigned __int8 uint8_t; + typedef __int8 int8_t; + #elif defined(UNIX_LP64) + // Use LP64 programming model from C_FLAGS for integer width declarations + + typedef unsigned long uint64_t; + typedef long int64_t; + typedef unsigned int uint32_t; + typedef int int32_t; + typedef unsigned short uint16_t; + typedef short int16_t; + typedef unsigned char uint8_t; + typedef char int8_t; + #else + // Assume P64 programming model from C_FLAGS for integer width declarations + + typedef unsigned long long uint64_t; + typedef long long int64_t; + typedef unsigned int uint32_t; + typedef int int32_t; + typedef unsigned short uint16_t; + typedef short int16_t; + typedef unsigned char uint8_t; + typedef char int8_t; + #endif + typedef uint64_t uintptr_t; + typedef int64_t intptr_t; +#elif defined(__GNUC__) + #include +#endif + +// +// Basic EFI types of various widths +// +#ifndef __WCHAR_TYPE__ +# define __WCHAR_TYPE__ short +#endif + + +typedef uint64_t UINT64; +typedef int64_t INT64; +typedef uint32_t UINT32; +typedef int32_t INT32; +typedef uint16_t UINT16; +typedef int16_t INT16; +typedef uint8_t UINT8; +typedef int8_t INT8; +typedef __WCHAR_TYPE__ WCHAR; + + +#undef VOID +#define VOID void + + +typedef int64_t INTN; +typedef uint64_t UINTN; + +//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// BugBug: Code to debug +// +#define BIT63 0x8000000000000000 + +#define PLATFORM_IOBASE_ADDRESS (0xffffc000000 | BIT63) +#define PORT_TO_MEMD(_Port) (PLATFORM_IOBASE_ADDRESS | ( ( ( (_Port) & 0xfffc) << 10 ) | ( (_Port) & 0x0fff) ) ) + +// +// Macro's with casts make this much easier to use and read. +// +#define PORT_TO_MEM8D(_Port) (*(UINT8 *)(PORT_TO_MEMD(_Port))) +#define POST_CODE(_Data) (PORT_TO_MEM8D(0x80) = (_Data)) +// +// BugBug: End Debug Code!!! +//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +#define EFIERR(a) (0x8000000000000000 | a) +#define EFI_ERROR_MASK 0x8000000000000000 +#define EFIERR_OEM(a) (0xc000000000000000 | a) + +#define BAD_POINTER 0xFBFBFBFBFBFBFBFB +#define MAX_ADDRESS 0xFFFFFFFFFFFFFFFF + +#define BREAKPOINT() while (TRUE) + +// +// Pointers must be aligned to these address to function +// you will get an alignment fault if this value is less than 8 +// +#define MIN_ALIGNMENT_SIZE 8 + +#define ALIGN_VARIABLE(Value , Adjustment) \ + (UINTN) Adjustment = 0; \ + if((UINTN)Value % MIN_ALIGNMENT_SIZE) \ + (UINTN)Adjustment = MIN_ALIGNMENT_SIZE - ((UINTN)Value % MIN_ALIGNMENT_SIZE); \ + Value = (UINTN)Value + (UINTN)Adjustment + +// +// Define macros to create data structure signatures. +// + +#define EFI_SIGNATURE_16(A,B) ((A) | (B<<8)) +#define EFI_SIGNATURE_32(A,B,C,D) (EFI_SIGNATURE_16(A,B) | (EFI_SIGNATURE_16(C,D) << 16)) +#define EFI_SIGNATURE_64(A,B,C,D,E,F,G,H) (EFI_SIGNATURE_32(A,B,C,D) | ((UINT64)(EFI_SIGNATURE_32(E,F,G,H)) << 32)) +// +// To export & import functions in the EFI emulator environment +// + + #define EXPORTAPI + +// +// EFIAPI - prototype calling convention for EFI function pointers +// BOOTSERVICE - prototype for implementation of a boot service interface +// RUNTIMESERVICE - prototype for implementation of a runtime service interface +// RUNTIMEFUNCTION - prototype for implementation of a runtime function that is not a service +// RUNTIME_CODE - pragma macro for declaring runtime code +// + +#ifndef EFIAPI // Forces EFI calling conventions reguardless of compiler options + #ifdef _MSC_EXTENSIONS + #define EFIAPI __cdecl // Force C calling convention for Microsoft C compiler + #else + #define EFIAPI // Substitute expresion to force C calling convention + #endif +#endif + +#define BOOTSERVICE +#define RUNTIMESERVICE +#define RUNTIMEFUNCTION + +#define RUNTIME_CODE(a) alloc_text("rtcode", a) +#define BEGIN_RUNTIME_DATA() data_seg("rtdata") +#define END_RUNTIME_DATA() data_seg("") + +#define VOLATILE volatile + +// +// BugBug: Need to find out if this is portable accross compliers. +// +#ifdef __GNUC__ +#define MEMORY_FENCE() __asm__ __volatile__ ("mf.a" ::: "memory") +#else +void __mf (void); +#pragma intrinsic (__mf) +#define MEMORY_FENCE() __mf() +#endif + +// +// When build similiar to FW, then link everything together as +// one big module. For the MSVC toolchain, we simply tell the +// linker what our driver init function is using /ENTRY. +// +#if defined(_MSC_EXTENSIONS) + #define EFI_DRIVER_ENTRY_POINT(InitFunction) \ + __pragma(comment(linker, "/ENTRY:" # InitFunction)) +#else + #define EFI_DRIVER_ENTRY_POINT(InitFunction) \ + UINTN \ + InitializeDriver ( \ + VOID *ImageHandle, \ + VOID *SystemTable \ + ) \ + { \ + return InitFunction(ImageHandle, \ + SystemTable); \ + } \ + \ + EFI_STATUS efi_main( \ + EFI_HANDLE image, \ + EFI_SYSTEM_TABLE *systab \ + ) __attribute__((weak, \ + alias ("InitializeDriver"))); +#endif + +#define LOAD_INTERNAL_DRIVER(_if, type, name, entry) \ + (_if)->LoadInternal(type, name, entry) + +// +// Some compilers don't support the forward reference construct: +// typedef struct XXXXX +// +// The following macro provide a workaround for such cases. +// +#ifdef NO_INTERFACE_DECL +#define INTERFACE_DECL(x) +#else +#if defined(__GNUC__) || defined(_MSC_EXTENSIONS) +#define INTERFACE_DECL(x) struct x +#else +#define INTERFACE_DECL(x) typedef struct x +#endif +#endif + +/* No efi call wrapper for IA32 architecture */ +#define uefi_call_wrapper(func, va_num, ...) func(__VA_ARGS__) +#define EFI_FUNCTION diff --git a/gnu-efi/inc/ia64/efilibplat.h b/gnu-efi/inc/ia64/efilibplat.h new file mode 100644 index 0000000..f07be3f --- /dev/null +++ b/gnu-efi/inc/ia64/efilibplat.h @@ -0,0 +1,80 @@ +#ifndef _EFI_LIB_PLAT_H +#define _EFI_LIB_PLAT_H +/*++ + +Copyright (c) 1998 Intel Corporation + +Module Name: + + efilibplat.h + +Abstract: + + EFI to compile bindings + + + +Revision History + +--*/ + +#include "salproc.h" + + +VOID +InitializeLibPlatform ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + +VOID +LibInitSalAndPalProc( + OUT PLABEL *SalPlabel, + OUT UINT64 *PalEntry + ); + +EFI_STATUS +LibGetSalIoPortMapping ( + OUT UINT64 *IoPortMapping + ); + +EFI_STATUS +LibGetSalIpiBlock ( + OUT UINT64 *IpiBlock + ); + +EFI_STATUS +LibGetSalWakeupVector ( + OUT UINT64 *WakeVector + ); + +VOID * +LibSearchSalSystemTable ( + IN UINT8 EntryType + ); + + +VOID +LibSalProc ( + IN UINT64 Arg1, + IN UINT64 Arg2, + IN UINT64 Arg3, + IN UINT64 Arg4, + IN UINT64 Arg5, + IN UINT64 Arg6, + IN UINT64 Arg7, + IN UINT64 Arg8, + OUT rArg *Results OPTIONAL + ); + +VOID +LibPalProc ( + IN UINT64 Arg1, + IN UINT64 Arg2, + IN UINT64 Arg3, + IN UINT64 Arg4, + OUT rArg *Results OPTIONAL + ); + +#endif + diff --git a/gnu-efi/inc/ia64/efisetjmp_arch.h b/gnu-efi/inc/ia64/efisetjmp_arch.h new file mode 100644 index 0000000..ceda448 --- /dev/null +++ b/gnu-efi/inc/ia64/efisetjmp_arch.h @@ -0,0 +1,47 @@ +#ifndef GNU_EFI_IA64_SETJMP_H +#define GNU_EFI_IA64_SETJMP_H + +#define JMPBUF_ALIGN 0x10 + +typedef struct { + UINT64 F2[2]; + UINT64 F3[2]; + UINT64 F4[2]; + UINT64 F5[2]; + UINT64 F16[2]; + UINT64 F17[2]; + UINT64 F18[2]; + UINT64 F19[2]; + UINT64 F20[2]; + UINT64 F21[2]; + UINT64 F22[2]; + UINT64 F23[2]; + UINT64 F24[2]; + UINT64 F25[2]; + UINT64 F26[2]; + UINT64 F27[2]; + UINT64 F28[2]; + UINT64 F29[2]; + UINT64 F30[2]; + UINT64 F31[2]; + UINT64 R4; + UINT64 R5; + UINT64 R6; + UINT64 R7; + UINT64 SP; + UINT64 BR0; + UINT64 BR1; + UINT64 BR2; + UINT64 BR3; + UINT64 BR4; + UINT64 BR5; + UINT64 InitialUNAT; + UINT64 AfterSpillUNAT; + UINT64 PFS; + UINT64 BSP; + UINT64 Predicates; + UINT64 LoopCount; + UINT64 FPSR; +} ALIGN(JMPBUF_ALIGN) jmp_buf[1]; + +#endif /* GNU_EFI_IA64_SETJMP_H */ diff --git a/gnu-efi/inc/ia64/pe.h b/gnu-efi/inc/ia64/pe.h new file mode 100644 index 0000000..b1cade2 --- /dev/null +++ b/gnu-efi/inc/ia64/pe.h @@ -0,0 +1,601 @@ +/* + PE32+ header file + */ +#ifndef _PE_H +#define _PE_H + +#define IMAGE_DOS_SIGNATURE 0x5A4D // MZ +#define IMAGE_OS2_SIGNATURE 0x454E // NE +#define IMAGE_OS2_SIGNATURE_LE 0x454C // LE +#define IMAGE_NT_SIGNATURE 0x00004550 // PE00 +#define IMAGE_EDOS_SIGNATURE 0x44454550 // PEED + +/***************************************************************************** + * The following stuff comes from winnt.h from the ia64sdk, plus the Plabel for + * loading EM executables. + *****************************************************************************/ +// +// Intel IA64 specific +// + +#define IMAGE_REL_BASED_IA64_IMM64 9 +#define IMAGE_REL_BASED_IA64_DIR64 10 + +struct Plabel { + UINT64 EntryPoint; + UINT64 NewGP; +}; + +typedef struct _IMAGE_DOS_HEADER { // DOS .EXE header + UINT16 e_magic; // Magic number + UINT16 e_cblp; // Bytes on last page of file + UINT16 e_cp; // Pages in file + UINT16 e_crlc; // Relocations + UINT16 e_cparhdr; // Size of header in paragraphs + UINT16 e_minalloc; // Minimum extra paragraphs needed + UINT16 e_maxalloc; // Maximum extra paragraphs needed + UINT16 e_ss; // Initial (relative) SS value + UINT16 e_sp; // Initial SP value + UINT16 e_csum; // Checksum + UINT16 e_ip; // Initial IP value + UINT16 e_cs; // Initial (relative) CS value + UINT16 e_lfarlc; // File address of relocation table + UINT16 e_ovno; // Overlay number + UINT16 e_res[4]; // Reserved words + UINT16 e_oemid; // OEM identifier (for e_oeminfo) + UINT16 e_oeminfo; // OEM information; e_oemid specific + UINT16 e_res2[10]; // Reserved words + UINT32 e_lfanew; // File address of new exe header + } IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER; + +typedef struct _IMAGE_OS2_HEADER { // OS/2 .EXE header + UINT16 ne_magic; // Magic number + UINT8 ne_ver; // Version number + UINT8 ne_rev; // Revision number + UINT16 ne_enttab; // Offset of Entry Table + UINT16 ne_cbenttab; // Number of bytes in Entry Table + UINT32 ne_crc; // Checksum of whole file + UINT16 ne_flags; // Flag UINT16 + UINT16 ne_autodata; // Automatic data segment number + UINT16 ne_heap; // Initial heap allocation + UINT16 ne_stack; // Initial stack allocation + UINT32 ne_csip; // Initial CS:IP setting + UINT32 ne_sssp; // Initial SS:SP setting + UINT16 ne_cseg; // Count of file segments + UINT16 ne_cmod; // Entries in Module Reference Table + UINT16 ne_cbnrestab; // Size of non-resident name table + UINT16 ne_segtab; // Offset of Segment Table + UINT16 ne_rsrctab; // Offset of Resource Table + UINT16 ne_restab; // Offset of resident name table + UINT16 ne_modtab; // Offset of Module Reference Table + UINT16 ne_imptab; // Offset of Imported Names Table + UINT32 ne_nrestab; // Offset of Non-resident Names Table + UINT16 ne_cmovent; // Count of movable entries + UINT16 ne_align; // Segment alignment shift count + UINT16 ne_cres; // Count of resource segments + UINT8 ne_exetyp; // Target Operating system + UINT8 ne_flagsothers; // Other .EXE flags + UINT16 ne_pretthunks; // offset to return thunks + UINT16 ne_psegrefbytes; // offset to segment ref. bytes + UINT16 ne_swaparea; // Minimum code swap area size + UINT16 ne_expver; // Expected Windows version number + } IMAGE_OS2_HEADER, *PIMAGE_OS2_HEADER; + +// +// File header format. +// + +typedef struct _IMAGE_FILE_HEADER { + UINT16 Machine; + UINT16 NumberOfSections; + UINT32 TimeDateStamp; + UINT32 PointerToSymbolTable; + UINT32 NumberOfSymbols; + UINT16 SizeOfOptionalHeader; + UINT16 Characteristics; +} IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER; + +#define IMAGE_SIZEOF_FILE_HEADER 20 + +#define IMAGE_FILE_RELOCS_STRIPPED 0x0001 // Relocation info stripped from file. +#define IMAGE_FILE_EXECUTABLE_IMAGE 0x0002 // File is executable (i.e. no unresolved externel references). +#define IMAGE_FILE_LINE_NUMS_STRIPPED 0x0004 // Line nunbers stripped from file. +#define IMAGE_FILE_LOCAL_SYMS_STRIPPED 0x0008 // Local symbols stripped from file. +#define IMAGE_FILE_BYTES_REVERSED_LO 0x0080 // Bytes of machine word are reversed. +#define IMAGE_FILE_32BIT_MACHINE 0x0100 // 32 bit word machine. +#define IMAGE_FILE_DEBUG_STRIPPED 0x0200 // Debugging info stripped from file in .DBG file +#define IMAGE_FILE_SYSTEM 0x1000 // System File. +#define IMAGE_FILE_DLL 0x2000 // File is a DLL. +#define IMAGE_FILE_BYTES_REVERSED_HI 0x8000 // Bytes of machine word are reversed. + +#define IMAGE_FILE_MACHINE_UNKNOWN 0 +#define IMAGE_FILE_MACHINE_I386 0x14c // Intel 386. +#define IMAGE_FILE_MACHINE_R3000 0x162 // MIPS little-endian, 0540 big-endian +#define IMAGE_FILE_MACHINE_R4000 0x166 // MIPS little-endian +#define IMAGE_FILE_MACHINE_ALPHA 0x184 // Alpha_AXP +#define IMAGE_FILE_MACHINE_ARMTHUMB_MIXED 0x1c2 // Arm/Thumb +#define IMAGE_FILE_MACHINE_POWERPC 0x1F0 // IBM PowerPC Little-Endian +#define IMAGE_FILE_MACHINE_IA64 0x200 // IA-64 +#define IMAGE_FILE_MACHINE_TAHOE 0x7cc // Intel EM machine +#define IMAGE_FILE_MACHINE_EBC 0xebc // EFI Byte Code +#define IMAGE_FILE_MACHINE_X64 0x8664 // x86_64 +// +// Directory format. +// + +typedef struct _IMAGE_DATA_DIRECTORY { + UINT32 VirtualAddress; + UINT32 Size; +} IMAGE_DATA_DIRECTORY, *PIMAGE_DATA_DIRECTORY; + +#define IMAGE_NUMBEROF_DIRECTORY_ENTRIES 16 + + +typedef struct _IMAGE_ROM_OPTIONAL_HEADER { + UINT16 Magic; + UINT8 MajorLinkerVersion; + UINT8 MinorLinkerVersion; + UINT32 SizeOfCode; + UINT32 SizeOfInitializedData; + UINT32 SizeOfUninitializedData; + UINT32 AddressOfEntryPoint; + UINT32 BaseOfCode; + UINT32 BaseOfData; + UINT32 BaseOfBss; + UINT32 GprMask; + UINT32 CprMask[4]; + UINT32 GpValue; +} IMAGE_ROM_OPTIONAL_HEADER, *PIMAGE_ROM_OPTIONAL_HEADER; + +typedef struct _IMAGE_OPTIONAL_HEADER { + UINT16 Magic; + UINT8 MajorLinkerVersion; + UINT8 MinorLinkerVersion; + UINT32 SizeOfCode; + UINT32 SizeOfInitializedData; + UINT32 SizeOfUninitializedData; + UINT32 AddressOfEntryPoint; + UINT32 BaseOfCode; + // UINT32 BaseOfData; + UINT64 ImageBase; + UINT32 SectionAlignment; + UINT32 FileAlignment; + UINT16 MajorOperatingSystemVersion; + UINT16 MinorOperatingSystemVersion; + UINT16 MajorImageVersion; + UINT16 MinorImageVersion; + UINT16 MajorSubsystemVersion; + UINT16 MinorSubsystemVersion; + UINT32 Win32VersionValue; + UINT32 SizeOfImage; + UINT32 SizeOfHeaders; + UINT32 CheckSum; + UINT16 Subsystem; + UINT16 DllCharacteristics; + UINT64 SizeOfStackReserve; + UINT64 SizeOfStackCommit; + UINT64 SizeOfHeapReserve; + UINT64 SizeOfHeapCommit; + UINT32 LoaderFlags; + UINT32 NumberOfRvaAndSizes; + IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES]; +} IMAGE_OPTIONAL_HEADER, *PIMAGE_OPTIONAL_HEADER; + + +#define IMAGE_SIZEOF_ROM_OPTIONAL_HEADER 56 +#define IMAGE_SIZEOF_STD_OPTIONAL_HEADER 28 +#define IMAGE_SIZEOF_NT_OPTIONAL_HEADER 224 +#define IMAGE_SIZEOF_NT_OPTIONAL64_HEADER 244 + +#define IMAGE_NT_OPTIONAL_HDR_MAGIC 0x10b +#define IMAGE_NT_OPTIONAL_HDR64_MAGIC 0x20b +#define IMAGE_ROM_OPTIONAL_HDR_MAGIC 0x107 + +typedef struct _IMAGE_NT_HEADERS { + UINT32 Signature; + IMAGE_FILE_HEADER FileHeader; + IMAGE_OPTIONAL_HEADER OptionalHeader; +} IMAGE_NT_HEADERS, *PIMAGE_NT_HEADERS; + +typedef struct _IMAGE_ROM_HEADERS { + IMAGE_FILE_HEADER FileHeader; + IMAGE_ROM_OPTIONAL_HEADER OptionalHeader; +} IMAGE_ROM_HEADERS, *PIMAGE_ROM_HEADERS; + +#define IMAGE_FIRST_SECTION( ntheader ) ((PIMAGE_SECTION_HEADER) \ + ((UINT32)ntheader + \ + FIELD_OFFSET( IMAGE_NT_HEADERS, OptionalHeader ) + \ + ((PIMAGE_NT_HEADERS)(ntheader))->FileHeader.SizeOfOptionalHeader \ + )) + + +// Subsystem Values + +#define IMAGE_SUBSYSTEM_UNKNOWN 0 // Unknown subsystem. +#define IMAGE_SUBSYSTEM_NATIVE 1 // Image doesn't require a subsystem. +#define IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem. +#define IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem. +#define IMAGE_SUBSYSTEM_OS2_CUI 5 // image runs in the OS/2 character subsystem. +#define IMAGE_SUBSYSTEM_POSIX_CUI 7 // image run in the Posix character subsystem. + + +// Directory Entries + +#define IMAGE_DIRECTORY_ENTRY_EXPORT 0 // Export Directory +#define IMAGE_DIRECTORY_ENTRY_IMPORT 1 // Import Directory +#define IMAGE_DIRECTORY_ENTRY_RESOURCE 2 // Resource Directory +#define IMAGE_DIRECTORY_ENTRY_EXCEPTION 3 // Exception Directory +#define IMAGE_DIRECTORY_ENTRY_SECURITY 4 // Security Directory +#define IMAGE_DIRECTORY_ENTRY_BASERELOC 5 // Base Relocation Table +#define IMAGE_DIRECTORY_ENTRY_DEBUG 6 // Debug Directory +#define IMAGE_DIRECTORY_ENTRY_COPYRIGHT 7 // Description String +#define IMAGE_DIRECTORY_ENTRY_GLOBALPTR 8 // Machine Value (MIPS GP) +#define IMAGE_DIRECTORY_ENTRY_TLS 9 // TLS Directory +#define IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG 10 // Load Configuration Directory + +// +// Section header format. +// + +#define IMAGE_SIZEOF_SHORT_NAME 8 + +typedef struct _IMAGE_SECTION_HEADER { + UINT8 Name[IMAGE_SIZEOF_SHORT_NAME]; + union { + UINT32 PhysicalAddress; + UINT32 VirtualSize; + } Misc; + UINT32 VirtualAddress; + UINT32 SizeOfRawData; + UINT32 PointerToRawData; + UINT32 PointerToRelocations; + UINT32 PointerToLinenumbers; + UINT16 NumberOfRelocations; + UINT16 NumberOfLinenumbers; + UINT32 Characteristics; +} IMAGE_SECTION_HEADER, *PIMAGE_SECTION_HEADER; + +#define IMAGE_SIZEOF_SECTION_HEADER 40 + +#define IMAGE_SCN_TYPE_NO_PAD 0x00000008 // Reserved. + +#define IMAGE_SCN_CNT_CODE 0x00000020 // Section contains code. +#define IMAGE_SCN_CNT_INITIALIZED_DATA 0x00000040 // Section contains initialized data. +#define IMAGE_SCN_CNT_UNINITIALIZED_DATA 0x00000080 // Section contains uninitialized data. + +#define IMAGE_SCN_LNK_OTHER 0x00000100 // Reserved. +#define IMAGE_SCN_LNK_INFO 0x00000200 // Section contains comments or some other type of information. +#define IMAGE_SCN_LNK_REMOVE 0x00000800 // Section contents will not become part of image. +#define IMAGE_SCN_LNK_COMDAT 0x00001000 // Section contents comdat. + +#define IMAGE_SCN_ALIGN_1BYTES 0x00100000 // +#define IMAGE_SCN_ALIGN_2BYTES 0x00200000 // +#define IMAGE_SCN_ALIGN_4BYTES 0x00300000 // +#define IMAGE_SCN_ALIGN_8BYTES 0x00400000 // +#define IMAGE_SCN_ALIGN_16BYTES 0x00500000 // Default alignment if no others are specified. +#define IMAGE_SCN_ALIGN_32BYTES 0x00600000 // +#define IMAGE_SCN_ALIGN_64BYTES 0x00700000 // + +#define IMAGE_SCN_MEM_DISCARDABLE 0x02000000 // Section can be discarded. +#define IMAGE_SCN_MEM_NOT_CACHED 0x04000000 // Section is not cachable. +#define IMAGE_SCN_MEM_NOT_PAGED 0x08000000 // Section is not pageable. +#define IMAGE_SCN_MEM_SHARED 0x10000000 // Section is shareable. +#define IMAGE_SCN_MEM_EXECUTE 0x20000000 // Section is executable. +#define IMAGE_SCN_MEM_READ 0x40000000 // Section is readable. +#define IMAGE_SCN_MEM_WRITE 0x80000000 // Section is writeable. + +// +// Symbol format. +// + + +#define IMAGE_SIZEOF_SYMBOL 18 + +// +// Section values. +// +// Symbols have a section number of the section in which they are +// defined. Otherwise, section numbers have the following meanings: +// + +#define IMAGE_SYM_UNDEFINED (UINT16)0 // Symbol is undefined or is common. +#define IMAGE_SYM_ABSOLUTE (UINT16)-1 // Symbol is an absolute value. +#define IMAGE_SYM_DEBUG (UINT16)-2 // Symbol is a special debug item. + +// +// Type (fundamental) values. +// + +#define IMAGE_SYM_TYPE_NULL 0 // no type. +#define IMAGE_SYM_TYPE_VOID 1 // +#define IMAGE_SYM_TYPE_CHAR 2 // type character. +#define IMAGE_SYM_TYPE_SHORT 3 // type short integer. +#define IMAGE_SYM_TYPE_INT 4 // +#define IMAGE_SYM_TYPE_LONG 5 // +#define IMAGE_SYM_TYPE_FLOAT 6 // +#define IMAGE_SYM_TYPE_DOUBLE 7 // +#define IMAGE_SYM_TYPE_STRUCT 8 // +#define IMAGE_SYM_TYPE_UNION 9 // +#define IMAGE_SYM_TYPE_ENUM 10 // enumeration. +#define IMAGE_SYM_TYPE_MOE 11 // member of enumeration. +#define IMAGE_SYM_TYPE_BYTE 12 // +#define IMAGE_SYM_TYPE_WORD 13 // +#define IMAGE_SYM_TYPE_UINT 14 // +#define IMAGE_SYM_TYPE_DWORD 15 // + +// +// Type (derived) values. +// + +#define IMAGE_SYM_DTYPE_NULL 0 // no derived type. +#define IMAGE_SYM_DTYPE_POINTER 1 // pointer. +#define IMAGE_SYM_DTYPE_FUNCTION 2 // function. +#define IMAGE_SYM_DTYPE_ARRAY 3 // array. + +// +// Storage classes. +// + +#define IMAGE_SYM_CLASS_END_OF_FUNCTION (BYTE )-1 +#define IMAGE_SYM_CLASS_NULL 0 +#define IMAGE_SYM_CLASS_AUTOMATIC 1 +#define IMAGE_SYM_CLASS_EXTERNAL 2 +#define IMAGE_SYM_CLASS_STATIC 3 +#define IMAGE_SYM_CLASS_REGISTER 4 +#define IMAGE_SYM_CLASS_EXTERNAL_DEF 5 +#define IMAGE_SYM_CLASS_LABEL 6 +#define IMAGE_SYM_CLASS_UNDEFINED_LABEL 7 +#define IMAGE_SYM_CLASS_MEMBER_OF_STRUCT 8 +#define IMAGE_SYM_CLASS_ARGUMENT 9 +#define IMAGE_SYM_CLASS_STRUCT_TAG 10 +#define IMAGE_SYM_CLASS_MEMBER_OF_UNION 11 +#define IMAGE_SYM_CLASS_UNION_TAG 12 +#define IMAGE_SYM_CLASS_TYPE_DEFINITION 13 +#define IMAGE_SYM_CLASS_UNDEFINED_STATIC 14 +#define IMAGE_SYM_CLASS_ENUM_TAG 15 +#define IMAGE_SYM_CLASS_MEMBER_OF_ENUM 16 +#define IMAGE_SYM_CLASS_REGISTER_PARAM 17 +#define IMAGE_SYM_CLASS_BIT_FIELD 18 +#define IMAGE_SYM_CLASS_BLOCK 100 +#define IMAGE_SYM_CLASS_FUNCTION 101 +#define IMAGE_SYM_CLASS_END_OF_STRUCT 102 +#define IMAGE_SYM_CLASS_FILE 103 +// new +#define IMAGE_SYM_CLASS_SECTION 104 +#define IMAGE_SYM_CLASS_WEAK_EXTERNAL 105 + +// type packing constants + +#define N_BTMASK 017 +#define N_TMASK 060 +#define N_TMASK1 0300 +#define N_TMASK2 0360 +#define N_BTSHFT 4 +#define N_TSHIFT 2 + +// MACROS + +// +// Communal selection types. +// + +#define IMAGE_COMDAT_SELECT_NODUPLICATES 1 +#define IMAGE_COMDAT_SELECT_ANY 2 +#define IMAGE_COMDAT_SELECT_SAME_SIZE 3 +#define IMAGE_COMDAT_SELECT_EXACT_MATCH 4 +#define IMAGE_COMDAT_SELECT_ASSOCIATIVE 5 + +#define IMAGE_WEAK_EXTERN_SEARCH_NOLIBRARY 1 +#define IMAGE_WEAK_EXTERN_SEARCH_LIBRARY 2 +#define IMAGE_WEAK_EXTERN_SEARCH_ALIAS 3 + + +// +// Relocation format. +// + +typedef struct _IMAGE_RELOCATION { + UINT32 VirtualAddress; + UINT32 SymbolTableIndex; + UINT16 Type; +} IMAGE_RELOCATION; + +#define IMAGE_SIZEOF_RELOCATION 10 + +// +// I386 relocation types. +// + +#define IMAGE_REL_I386_ABSOLUTE 0 // Reference is absolute, no relocation is necessary +#define IMAGE_REL_I386_DIR16 01 // Direct 16-bit reference to the symbols virtual address +#define IMAGE_REL_I386_REL16 02 // PC-relative 16-bit reference to the symbols virtual address +#define IMAGE_REL_I386_DIR32 06 // Direct 32-bit reference to the symbols virtual address +#define IMAGE_REL_I386_DIR32NB 07 // Direct 32-bit reference to the symbols virtual address, base not included +#define IMAGE_REL_I386_SEG12 011 // Direct 16-bit reference to the segment-selector bits of a 32-bit virtual address +#define IMAGE_REL_I386_SECTION 012 +#define IMAGE_REL_I386_SECREL 013 +#define IMAGE_REL_I386_REL32 024 // PC-relative 32-bit reference to the symbols virtual address + +// +// MIPS relocation types. +// + +#define IMAGE_REL_MIPS_ABSOLUTE 0 // Reference is absolute, no relocation is necessary +#define IMAGE_REL_MIPS_REFHALF 01 +#define IMAGE_REL_MIPS_REFWORD 02 +#define IMAGE_REL_MIPS_JMPADDR 03 +#define IMAGE_REL_MIPS_REFHI 04 +#define IMAGE_REL_MIPS_REFLO 05 +#define IMAGE_REL_MIPS_GPREL 06 +#define IMAGE_REL_MIPS_LITERAL 07 +#define IMAGE_REL_MIPS_SECTION 012 +#define IMAGE_REL_MIPS_SECREL 013 +#define IMAGE_REL_MIPS_REFWORDNB 042 +#define IMAGE_REL_MIPS_PAIR 045 + +// +// Alpha Relocation types. +// + +#define IMAGE_REL_ALPHA_ABSOLUTE 0x0 +#define IMAGE_REL_ALPHA_REFLONG 0x1 +#define IMAGE_REL_ALPHA_REFQUAD 0x2 +#define IMAGE_REL_ALPHA_GPREL32 0x3 +#define IMAGE_REL_ALPHA_LITERAL 0x4 +#define IMAGE_REL_ALPHA_LITUSE 0x5 +#define IMAGE_REL_ALPHA_GPDISP 0x6 +#define IMAGE_REL_ALPHA_BRADDR 0x7 +#define IMAGE_REL_ALPHA_HINT 0x8 +#define IMAGE_REL_ALPHA_INLINE_REFLONG 0x9 +#define IMAGE_REL_ALPHA_REFHI 0xA +#define IMAGE_REL_ALPHA_REFLO 0xB +#define IMAGE_REL_ALPHA_PAIR 0xC +#define IMAGE_REL_ALPHA_MATCH 0xD +#define IMAGE_REL_ALPHA_SECTION 0xE +#define IMAGE_REL_ALPHA_SECREL 0xF +#define IMAGE_REL_ALPHA_REFLONGNB 0x10 + +// +// IBM PowerPC relocation types. +// + +#define IMAGE_REL_PPC_ABSOLUTE 0x0000 // NOP +#define IMAGE_REL_PPC_ADDR64 0x0001 // 64-bit address +#define IMAGE_REL_PPC_ADDR32 0x0002 // 32-bit address +#define IMAGE_REL_PPC_ADDR24 0x0003 // 26-bit address, shifted left 2 (branch absolute) +#define IMAGE_REL_PPC_ADDR16 0x0004 // 16-bit address +#define IMAGE_REL_PPC_ADDR14 0x0005 // 16-bit address, shifted left 2 (load doubleword) +#define IMAGE_REL_PPC_REL24 0x0006 // 26-bit PC-relative offset, shifted left 2 (branch relative) +#define IMAGE_REL_PPC_REL14 0x0007 // 16-bit PC-relative offset, shifted left 2 (br cond relative) +#define IMAGE_REL_PPC_TOCREL16 0x0008 // 16-bit offset from TOC base +#define IMAGE_REL_PPC_TOCREL14 0x0009 // 16-bit offset from TOC base, shifted left 2 (load doubleword) + +#define IMAGE_REL_PPC_ADDR32NB 0x000A // 32-bit addr w/o image base +#define IMAGE_REL_PPC_SECREL 0x000B // va of containing section (as in an image sectionhdr) +#define IMAGE_REL_PPC_SECTION 0x000C // sectionheader number +#define IMAGE_REL_PPC_IFGLUE 0x000D // substitute TOC restore instruction iff symbol is glue code +#define IMAGE_REL_PPC_IMGLUE 0x000E // symbol is glue code; virtual address is TOC restore instruction + +#define IMAGE_REL_PPC_TYPEMASK 0x00FF // mask to isolate above values in IMAGE_RELOCATION.Type + +// Flag bits in IMAGE_RELOCATION.TYPE + +#define IMAGE_REL_PPC_NEG 0x0100 // subtract reloc value rather than adding it +#define IMAGE_REL_PPC_BRTAKEN 0x0200 // fix branch prediction bit to predict branch taken +#define IMAGE_REL_PPC_BRNTAKEN 0x0400 // fix branch prediction bit to predict branch not taken +#define IMAGE_REL_PPC_TOCDEFN 0x0800 // toc slot defined in file (or, data in toc) + +// +// Based relocation format. +// + +typedef struct _IMAGE_BASE_RELOCATION { + UINT32 VirtualAddress; + UINT32 SizeOfBlock; +// UINT16 TypeOffset[1]; +} IMAGE_BASE_RELOCATION, *PIMAGE_BASE_RELOCATION; + +#define IMAGE_SIZEOF_BASE_RELOCATION 8 + +// +// Based relocation types. +// + +#define IMAGE_REL_BASED_ABSOLUTE 0 +#define IMAGE_REL_BASED_HIGH 1 +#define IMAGE_REL_BASED_LOW 2 +#define IMAGE_REL_BASED_HIGHLOW 3 +#define IMAGE_REL_BASED_HIGHADJ 4 +#define IMAGE_REL_BASED_MIPS_JMPADDR 5 +#define IMAGE_REL_BASED_IA64_IMM64 9 +#define IMAGE_REL_BASED_DIR64 10 + +// +// Line number format. +// + +typedef struct _IMAGE_LINENUMBER { + union { + UINT32 SymbolTableIndex; // Symbol table index of function name if Linenumber is 0. + UINT32 VirtualAddress; // Virtual address of line number. + } Type; + UINT16 Linenumber; // Line number. +} IMAGE_LINENUMBER; + +#define IMAGE_SIZEOF_LINENUMBER 6 + +// +// Archive format. +// + +#define IMAGE_ARCHIVE_START_SIZE 8 +#define IMAGE_ARCHIVE_START "!\n" +#define IMAGE_ARCHIVE_END "`\n" +#define IMAGE_ARCHIVE_PAD "\n" +#define IMAGE_ARCHIVE_LINKER_MEMBER "/ " +#define IMAGE_ARCHIVE_LONGNAMES_MEMBER "// " + +typedef struct _IMAGE_ARCHIVE_MEMBER_HEADER { + UINT8 Name[16]; // File member name - `/' terminated. + UINT8 Date[12]; // File member date - decimal. + UINT8 UserID[6]; // File member user id - decimal. + UINT8 GroupID[6]; // File member group id - decimal. + UINT8 Mode[8]; // File member mode - octal. + UINT8 Size[10]; // File member size - decimal. + UINT8 EndHeader[2]; // String to end header. +} IMAGE_ARCHIVE_MEMBER_HEADER, *PIMAGE_ARCHIVE_MEMBER_HEADER; + +#define IMAGE_SIZEOF_ARCHIVE_MEMBER_HDR 60 + +// +// DLL support. +// + +// +// Export Format +// + +typedef struct _IMAGE_EXPORT_DIRECTORY { + UINT32 Characteristics; + UINT32 TimeDateStamp; + UINT16 MajorVersion; + UINT16 MinorVersion; + UINT32 Name; + UINT32 Base; + UINT32 NumberOfFunctions; + UINT32 NumberOfNames; + UINT32 AddressOfFunctions; + UINT32 AddressOfNames; + UINT32 AddressOfNameOrdinals; +} IMAGE_EXPORT_DIRECTORY, *PIMAGE_EXPORT_DIRECTORY; + +// +// Import Format +// + +typedef struct _IMAGE_IMPORT_BY_NAME { + UINT16 Hint; + UINT8 Name[1]; +} IMAGE_IMPORT_BY_NAME, *PIMAGE_IMPORT_BY_NAME; + +typedef struct _IMAGE_THUNK_DATA { + union { + UINT32 Function; + UINT32 Ordinal; + PIMAGE_IMPORT_BY_NAME AddressOfData; + } u1; +} IMAGE_THUNK_DATA, *PIMAGE_THUNK_DATA; + +#define IMAGE_ORDINAL_FLAG 0x80000000 +#define IMAGE_SNAP_BY_ORDINAL(Ordinal) ((Ordinal & IMAGE_ORDINAL_FLAG) != 0) +#define IMAGE_ORDINAL(Ordinal) (Ordinal & 0xffff) + +typedef struct _IMAGE_IMPORT_DESCRIPTOR { + UINT32 Characteristics; + UINT32 TimeDateStamp; + UINT32 ForwarderChain; + UINT32 Name; + PIMAGE_THUNK_DATA FirstThunk; +} IMAGE_IMPORT_DESCRIPTOR, *PIMAGE_IMPORT_DESCRIPTOR; + +#endif diff --git a/gnu-efi/inc/ia64/salproc.h b/gnu-efi/inc/ia64/salproc.h new file mode 100644 index 0000000..62a5dca --- /dev/null +++ b/gnu-efi/inc/ia64/salproc.h @@ -0,0 +1,264 @@ +#ifndef _SAL_PROC_H +#define _SAL_PROC_H +// +// +//Copyright (c) 1999 Intel Corporation +// +//Module Name: +// +// SalProc.h +// +//Abstract: +// +// Main SAL interface routins for IA-64 calls. +// +// +//Revision History +// +// + +// return value that mimicks r8,r9,r10 & r11 registers +typedef struct { + UINT64 p0; + UINT64 p1; + UINT64 p2; + UINT64 p3; +} rArg; + +#define SAL_PCI_CONFIG_READ 0x01000010 +#define SAL_PCI_CONFIG_WRITE 0x01000011 + +typedef VOID (*PFN)(); +typedef rArg (*PFN_SAL_PROC)(UINT64,UINT64,UINT64,UINT64,UINT64,UINT64,UINT64,UINT64); +typedef rArg (*PFN_SAL_CALLBACK)(UINT64,UINT64,UINT64,UINT64,UINT64,UINT64,UINT64,UINT64); + +typedef struct _PLABEL { + UINT64 ProcEntryPoint; + UINT64 GP; +} PLABEL; + +typedef struct tagIA32_BIOS_REGISTER_STATE { + + // general registers + UINT32 eax; + UINT32 ecx; + UINT32 edx; + UINT32 ebx; + + // stack registers + UINT32 esp; + UINT32 ebp; + UINT32 esi; + UINT32 edi; + + // eflags + UINT32 eflags; + + // instruction pointer + UINT32 eip; + + UINT16 cs; + UINT16 ds; + UINT16 es; + UINT16 fs; + UINT16 gs; + UINT16 ss; + + // Reserved + UINT32 Reserved1; + UINT64 Reserved2; +} IA32_BIOS_REGISTER_STATE; + +VOID EFIInitMsg(VOID); + +EFI_STATUS +PlRegisterAndStartTimer( + IN UINTN Period + ); + +EFI_STATUS +PlDeRegisterAndCancelTimer(VOID); + +VOID +SalProc ( + IN UINT64 Arg1, + IN UINT64 Arg2, + IN UINT64 Arg3, + IN UINT64 Arg4, + IN UINT64 Arg5, + IN UINT64 Arg6, + IN UINT64 Arg7, + IN UINT64 Arg8, + OUT rArg *Results OPTIONAL + ); + +VOID +SalCallBack ( + IN UINT64 Arg1, + IN UINT64 Arg2, + IN UINT64 Arg3, + IN UINT64 Arg4, + IN UINT64 Arg5, + IN UINT64 Arg6, + IN UINT64 Arg7, + IN UINT64 Arg8, + OUT rArg *Results OPTIONAL + ); + +VOID +RUNTIMEFUNCTION +RtSalCallBack ( + IN UINT64 Arg1, + IN UINT64 Arg2, + IN UINT64 Arg3, + IN UINT64 Arg4, + IN UINT64 Arg5, + IN UINT64 Arg6, + IN UINT64 Arg7, + IN UINT64 Arg8, + OUT rArg *Results OPTIONAL + ); + + +extern PLABEL RtGlobalSalProcEntry; +extern PLABEL RtGlobalSALCallBack; + +#pragma pack(1) +// +// SAL System Table +// +typedef struct { + UINT32 Signature; + UINT32 Length; + UINT16 Revision; + UINT16 EntryCount; + UINT8 CheckSum; + UINT8 Reserved[7]; + UINT16 SALA_Ver; + UINT16 SALB_Ver; + UINT8 OemId[32]; + UINT8 ProductID[32]; + UINT8 Reserved2[8]; +} SAL_SYSTEM_TABLE_HDR; + +#define SAL_ST_ENTRY_POINT 0 +#define SAL_ST_MEMORY_DESCRIPTOR 1 +#define SAL_ST_PLATFORM_FEATURES 2 +#define SAL_ST_TR_USAGE 3 +#define SAL_ST_PTC 4 +#define SAL_ST_AP_WAKEUP 5 + +typedef struct { + UINT8 Type; // Type == 0 + UINT8 Reserved[7]; + UINT64 PalProcEntry; + UINT64 SalProcEntry; + UINT64 GlobalDataPointer; + UINT64 Reserved2[2]; +} SAL_ST_ENTRY_POINT_DESCRIPTOR; + +typedef struct { + UINT8 Type; // Type == 1 + UINT8 NeedVirtualRegistration; + UINT8 MemoryAttributes; + UINT8 PageAccessRights; + UINT8 SupportedAttributes; + UINT8 Reserved; + UINT16 MemoryType; + UINT64 PhysicalMemoryAddress; + UINT32 Length; + UINT32 Reserved1; + UINT64 OemReserved; +} SAL_ST_MEMORY_DESCRIPTOR_ENTRY; + +// +// MemoryType info +// +#define SAL_SAPIC_IPI_BLOCK 0x0002 +#define SAL_IO_PORT_MAPPING 0x0003 + +typedef struct { + UINT8 Type; // Type == 2 + UINT8 PlatformFeatures; + UINT8 Reserved[14]; +} SAL_ST_MEMORY_DECRIPTOR; + +typedef struct { + UINT8 Type; // Type == 3 + UINT8 TRType; + UINT8 TRNumber; + UINT8 Reserved[5]; + UINT64 VirtualAddress; + UINT64 EncodedPageSize; + UINT64 Reserved1; +} SAL_ST_TR_DECRIPTOR; + +typedef struct { + UINT64 NumberOfProcessors; + UINT64 LocalIDRegister; +} SAL_COHERENCE_DOMAIN_INFO; + +typedef struct { + UINT8 Type; // Type == 4 + UINT8 Reserved[3]; + UINT32 NumberOfDomains; + SAL_COHERENCE_DOMAIN_INFO *DomainInformation; +} SAL_ST_CACHE_COHERENCE_DECRIPTOR; + +typedef struct { + UINT8 Type; // Type == 5 + UINT8 WakeUpType; + UINT8 Reserved[6]; + UINT64 ExternalInterruptVector; +} SAL_ST_AP_WAKEUP_DECRIPTOR; + +typedef struct { + SAL_SYSTEM_TABLE_HDR Header; + SAL_ST_ENTRY_POINT_DESCRIPTOR Entry0; +} SAL_SYSTEM_TABLE_ASCENDING_ORDER; + +#define FIT_ENTRY_PTR (0x100000000 - 32) // 4GB - 24 +#define FIT_PALA_ENTRY (0x100000000 - 48) // 4GB - 32 +#define FIT_PALB_TYPE 01 + +typedef struct { + UINT64 Address; + UINT8 Size[3]; + UINT8 Reserved; + UINT16 Revision; + UINT8 Type:7; + UINT8 CheckSumValid:1; + UINT8 CheckSum; +} FIT_ENTRY; + +#pragma pack() + +typedef + rArg +(*CALL_SAL_PROC)( + IN UINT64 Arg1, + IN UINT64 Arg2, + IN UINT64 Arg3, + IN UINT64 Arg4, + IN UINT64 Arg5, + IN UINT64 Arg6, + IN UINT64 Arg7, + IN UINT64 Arg8 + ); + +typedef + rArg +(*CALL_PAL_PROC)( + IN UINT64 Arg1, + IN UINT64 Arg2, + IN UINT64 Arg3, + IN UINT64 Arg4 + ); + +extern CALL_SAL_PROC GlobalSalProc; +extern CALL_PAL_PROC GlobalPalProc; +extern PLABEL SalProcPlabel; +extern PLABEL PalProcPlabel; + +#endif + diff --git a/gnu-efi/inc/inc.mak b/gnu-efi/inc/inc.mak new file mode 100644 index 0000000..992996b --- /dev/null +++ b/gnu-efi/inc/inc.mak @@ -0,0 +1,23 @@ + + +INC_DEPS = $(INC_DEPS) \ + efi.h \ + efiapi.h \ + efibind.h \ + eficon.h \ + efidebug.h \ + efidef.h \ + efidevp.h \ + efierr.h \ + efifs.h \ + efilib.h \ + efipart.h \ + efipciio.h \ + efiprot.h \ + efipxe.h \ + efivar.h \ + pe.h \ + efiip.h \ + efiudp.h \ + efitcp.h \ + stdarg.h diff --git a/gnu-efi/inc/libsmbios.h b/gnu-efi/inc/libsmbios.h new file mode 100644 index 0000000..658c01d --- /dev/null +++ b/gnu-efi/inc/libsmbios.h @@ -0,0 +1,143 @@ +#ifndef _LIB_SMBIOS_H +#define _LIB_SMBIOS_H +/*++ + +Copyright (c) 2000 Intel Corporation + +Module Name: + + LibSmbios.h + +Abstract: + + Lib include for SMBIOS services. Used to get system serial number and GUID + +Revision History + +--*/ + +// +// Define SMBIOS tables. +// +#pragma pack(1) +typedef struct { + UINT8 AnchorString[4]; + UINT8 EntryPointStructureChecksum; + UINT8 EntryPointLength; + UINT8 MajorVersion; + UINT8 MinorVersion; + UINT16 MaxStructureSize; + UINT8 EntryPointRevision; + UINT8 FormattedArea[5]; + UINT8 IntermediateAnchorString[5]; + UINT8 IntermediateChecksum; + UINT16 TableLength; + UINT32 TableAddress; + UINT16 NumberOfSmbiosStructures; + UINT8 SmbiosBcdRevision; +} SMBIOS_STRUCTURE_TABLE; + +typedef struct { + UINT8 AnchorString[5]; + UINT8 EntryPointStructureChecksum; + UINT8 EntryPointLength; + UINT8 MajorVersion; + UINT8 MinorVersion; + UINT8 DocRev; + UINT8 EntryPointRevision; + UINT8 Reserved; + UINT32 TableMaximumSize; + UINT64 TableAddress; +} SMBIOS3_STRUCTURE_TABLE; + +// +// Please note that SMBIOS structures can be odd byte aligned since the +// unformated section of each record is a set of arbitrary size strings. +// + +typedef struct { + UINT8 Type; + UINT8 Length; + UINT8 Handle[2]; +} SMBIOS_HEADER; + +typedef UINT8 SMBIOS_STRING; + +typedef struct { + SMBIOS_HEADER Hdr; + SMBIOS_STRING Vendor; + SMBIOS_STRING BiosVersion; + UINT8 BiosSegment[2]; + SMBIOS_STRING BiosReleaseDate; + UINT8 BiosSize; + UINT8 BiosCharacteristics[8]; +} SMBIOS_TYPE0; + +typedef struct { + SMBIOS_HEADER Hdr; + SMBIOS_STRING Manufacturer; + SMBIOS_STRING ProductName; + SMBIOS_STRING Version; + SMBIOS_STRING SerialNumber; + + // + // always byte copy this data to prevent alignment faults! + // + EFI_GUID Uuid; + + UINT8 WakeUpType; +} SMBIOS_TYPE1; + +typedef struct { + SMBIOS_HEADER Hdr; + SMBIOS_STRING Manufacturer; + SMBIOS_STRING ProductName; + SMBIOS_STRING Version; + SMBIOS_STRING SerialNumber; +} SMBIOS_TYPE2; + +typedef struct { + SMBIOS_HEADER Hdr; + SMBIOS_STRING Manufacturer; + UINT8 Type; + SMBIOS_STRING Version; + SMBIOS_STRING SerialNumber; + SMBIOS_STRING AssetTag; + UINT8 BootupState; + UINT8 PowerSupplyState; + UINT8 ThermalState; + UINT8 SecurityStatus; + UINT8 OemDefined[4]; +} SMBIOS_TYPE3; + +typedef struct { + SMBIOS_HEADER Hdr; + UINT8 Socket; + UINT8 ProcessorType; + UINT8 ProcessorFamily; + SMBIOS_STRING ProcessorManufacture; + UINT8 ProcessorId[8]; + SMBIOS_STRING ProcessorVersion; + UINT8 Voltage; + UINT8 ExternalClock[2]; + UINT8 MaxSpeed[2]; + UINT8 CurrentSpeed[2]; + UINT8 Status; + UINT8 ProcessorUpgrade; + UINT8 L1CacheHandle[2]; + UINT8 L2CacheHandle[2]; + UINT8 L3CacheHandle[2]; +} SMBIOS_TYPE4; + +typedef union { + SMBIOS_HEADER *Hdr; + SMBIOS_TYPE0 *Type0; + SMBIOS_TYPE1 *Type1; + SMBIOS_TYPE2 *Type2; + SMBIOS_TYPE3 *Type3; + SMBIOS_TYPE4 *Type4; + UINT8 *Raw; +} SMBIOS_STRUCTURE_POINTER; +#pragma pack() + +#endif diff --git a/gnu-efi/inc/make.inf b/gnu-efi/inc/make.inf new file mode 100644 index 0000000..f173196 --- /dev/null +++ b/gnu-efi/inc/make.inf @@ -0,0 +1,33 @@ +# +# +# + +[sources] + efi.h + efiapi.h + eficon.h + efidebug.h + efidef.h + efidevp.h + efierr.h + efifs.h + efilib.h + efipart.h + efipciio.h + efiprot.h + efipxebc.h + efistdarg.h + efinet.h + efiip.h + efiudp.h + efitcp.h + +[ia32sources] + efibind.h + pe.h + efilibplat.h + +[ia64sources] + efibind.h + pe.h + efilibplat.h diff --git a/gnu-efi/inc/makefile.hdr b/gnu-efi/inc/makefile.hdr new file mode 100644 index 0000000..46ef387 --- /dev/null +++ b/gnu-efi/inc/makefile.hdr @@ -0,0 +1,48 @@ + +# +# This is a machine generated file - DO NOT EDIT +# Generated by genmake.exe +# Generated from make.inf +# Copyright (c) 1998 Intel Corporation +# + +INC_DEPS = $(INC_DEPS) \ + $(SDK_INSTALL_DIR)\include\efi\efi.h \ + $(SDK_INSTALL_DIR)\include\efi\efiapi.h \ + $(SDK_INSTALL_DIR)\include\efi\eficon.h \ + $(SDK_INSTALL_DIR)\include\efi\efidebug.h \ + $(SDK_INSTALL_DIR)\include\efi\efidef.h \ + $(SDK_INSTALL_DIR)\include\efi\efidevp.h \ + $(SDK_INSTALL_DIR)\include\efi\efierr.h \ + $(SDK_INSTALL_DIR)\include\efi\efifs.h \ + $(SDK_INSTALL_DIR)\include\efi\efilib.h \ + $(SDK_INSTALL_DIR)\include\efi\efipart.h \ + $(SDK_INSTALL_DIR)\include\efi\efipciio.h \ + $(SDK_INSTALL_DIR)\include\efi\efiprot.h \ + $(SDK_INSTALL_DIR)\include\efi\efipxebc.h \ + $(SDK_INSTALL_DIR)\include\efi\efistdarg.h \ + $(SDK_INSTALL_DIR)\include\efi\efinet.h \ + $(SDK_INSTALL_DIR)\include\efi\efiip.h \ + $(SDK_INSTALL_DIR)\include\efi\efiudp.h \ + $(SDK_INSTALL_DIR)\include\efi\efitcp.h \ + + +!IF "$(PROCESSOR)" == "Ia32" +INC_DEPS = $(INC_DEPS) \ + $(SDK_INSTALL_DIR)\include\efi\Ia32\efibind.h \ + $(SDK_INSTALL_DIR)\include\efi\Ia32\pe.h \ + $(SDK_INSTALL_DIR)\include\efi\Ia32\efilibplat.h \ + + +!ENDIF + + +!IF "$(PROCESSOR)" == "Ia64" +INC_DEPS = $(INC_DEPS) \ + $(SDK_INSTALL_DIR)\include\efi\Ia64\efibind.h \ + $(SDK_INSTALL_DIR)\include\efi\Ia64\pe.h \ + $(SDK_INSTALL_DIR)\include\efi\Ia64\efilibplat.h \ + + +!ENDIF + diff --git a/gnu-efi/inc/mips64el/efibind.h b/gnu-efi/inc/mips64el/efibind.h new file mode 100644 index 0000000..1f08cd3 --- /dev/null +++ b/gnu-efi/inc/mips64el/efibind.h @@ -0,0 +1,166 @@ +/* + * Copright (C) 2014 - 2015 Linaro Ltd. + * Author: Ard Biesheuvel + * Copright (C) 2017 Lemote Co. + * Author: Heiher + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice and this list of conditions, without modification. + * 2. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * Alternatively, this software may be distributed 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. + */ + +#if !defined(__STDC_VERSION__) || (__STDC_VERSION__ < 199901L ) && !defined(__cplusplus) + +// ANSI C 1999/2000 stdint.h integer width declarations + +typedef unsigned long uint64_t; +typedef long int64_t; +typedef unsigned int uint32_t; +typedef int int32_t; +typedef unsigned short uint16_t; +typedef short int16_t; +typedef unsigned char uint8_t; +typedef signed char int8_t; // unqualified 'char' is unsigned on ARM +typedef uint64_t uintptr_t; +typedef int64_t intptr_t; + +#else +#include +#endif + +// +// Basic EFI types of various widths +// + +#ifndef __WCHAR_TYPE__ +# define __WCHAR_TYPE__ short +#endif + +typedef uint64_t UINT64; +typedef int64_t INT64; + +typedef uint32_t UINT32; +typedef int32_t INT32; + +typedef uint16_t UINT16; +typedef int16_t INT16; +typedef uint8_t UINT8; +typedef int8_t INT8; +typedef __WCHAR_TYPE__ WCHAR; + +#undef VOID +#define VOID void + +typedef int64_t INTN; +typedef uint64_t UINTN; + +#define EFIERR(a) (0x8000000000000000 | a) +#define EFI_ERROR_MASK 0x8000000000000000 +#define EFIERR_OEM(a) (0xc000000000000000 | a) + +#define BAD_POINTER 0xFBFBFBFBFBFBFBFB +#define MAX_ADDRESS 0xFFFFFFFFFFFFFFFF + +#define BREAKPOINT() while (TRUE); // Make it hang on Bios[Dbg]32 + +// +// Pointers must be aligned to these address to function +// + +#define MIN_ALIGNMENT_SIZE 8 + +#define ALIGN_VARIABLE(Value ,Adjustment) \ + (UINTN)Adjustment = 0; \ + if((UINTN)Value % MIN_ALIGNMENT_SIZE) \ + (UINTN)Adjustment = MIN_ALIGNMENT_SIZE - ((UINTN)Value % MIN_ALIGNMENT_SIZE); \ + Value = (UINTN)Value + (UINTN)Adjustment + + +// +// Define macros to build data structure signatures from characters. +// + +#define EFI_SIGNATURE_16(A,B) ((A) | (B<<8)) +#define EFI_SIGNATURE_32(A,B,C,D) (EFI_SIGNATURE_16(A,B) | (EFI_SIGNATURE_16(C,D) << 16)) +#define EFI_SIGNATURE_64(A,B,C,D,E,F,G,H) (EFI_SIGNATURE_32(A,B,C,D) | ((UINT64)(EFI_SIGNATURE_32(E,F,G,H)) << 32)) + +// +// EFIAPI - prototype calling convention for EFI function pointers +// BOOTSERVICE - prototype for implementation of a boot service interface +// RUNTIMESERVICE - prototype for implementation of a runtime service interface +// RUNTIMEFUNCTION - prototype for implementation of a runtime function that is not a service +// RUNTIME_CODE - pragma macro for declaring runtime code +// + +#ifndef EFIAPI // Forces EFI calling conventions reguardless of compiler options +#define EFIAPI // Substitute expresion to force C calling convention +#endif + +#define BOOTSERVICE +#define RUNTIMESERVICE +#define RUNTIMEFUNCTION + + +#define RUNTIME_CODE(a) alloc_text("rtcode", a) +#define BEGIN_RUNTIME_DATA() data_seg("rtdata") +#define END_RUNTIME_DATA() data_seg("") + +#define VOLATILE volatile + +#define MEMORY_FENCE __sync_synchronize + +// +// When build similiar to FW, then link everything together as +// one big module. +// + +#define EFI_DRIVER_ENTRY_POINT(InitFunction) \ + UINTN \ + InitializeDriver ( \ + VOID *ImageHandle, \ + VOID *SystemTable \ + ) \ + { \ + return InitFunction(ImageHandle, \ + SystemTable); \ + } \ + \ + EFI_STATUS efi_main( \ + EFI_HANDLE image, \ + EFI_SYSTEM_TABLE *systab \ + ) __attribute__((weak, \ + alias ("InitializeDriver"))); + +#define LOAD_INTERNAL_DRIVER(_if, type, name, entry) \ + (_if)->LoadInternal(type, name, entry) + + +// +// Some compilers don't support the forward reference construct: +// typedef struct XXXXX +// +// The following macro provide a workaround for such cases. + +#define INTERFACE_DECL(x) struct x + +#define uefi_call_wrapper(func, va_num, ...) func(__VA_ARGS__) +#define EFI_FUNCTION + +static inline UINT64 swap_uint64 (UINT64 v) +{ + asm volatile ( + "dsbh %[v], %[v] \n\t" + "dshd %[v], %[v] \n\t" + :[v]"+r"(v) + ); + + return v; +} diff --git a/gnu-efi/inc/mips64el/efilibplat.h b/gnu-efi/inc/mips64el/efilibplat.h new file mode 100644 index 0000000..70a0786 --- /dev/null +++ b/gnu-efi/inc/mips64el/efilibplat.h @@ -0,0 +1,25 @@ +/*++ + +Copyright (c) 1998 Intel Corporation + +Module Name: + + efilibplat.h + +Abstract: + + EFI to compile bindings + + + + +Revision History + +--*/ + +VOID +InitializeLibPlatform ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + diff --git a/gnu-efi/inc/mips64el/efisetjmp_arch.h b/gnu-efi/inc/mips64el/efisetjmp_arch.h new file mode 100644 index 0000000..2b8f756 --- /dev/null +++ b/gnu-efi/inc/mips64el/efisetjmp_arch.h @@ -0,0 +1,34 @@ +#ifndef GNU_EFI_MIPS64EL_SETJMP_H +#define GNU_EFI_MIPS64EL_SETJMP_H + +#define JMPBUF_ALIGN 8 + +typedef struct { + /* GP regs */ + UINT64 RA; + UINT64 SP; + UINT64 FP; + UINT64 GP; + UINT64 S0; + UINT64 S1; + UINT64 S2; + UINT64 S3; + UINT64 S4; + UINT64 S5; + UINT64 S6; + UINT64 S7; + +#ifdef __mips_hard_float + /* FP regs */ + UINT64 F24; + UINT64 F25; + UINT64 F26; + UINT64 F27; + UINT64 F28; + UINT64 F29; + UINT64 F30; + UINT64 F31; +#endif +} ALIGN(JMPBUF_ALIGN) jmp_buf[1]; + +#endif /* GNU_EFI_MIPS64EL_SETJMP_H */ diff --git a/gnu-efi/inc/pci22.h b/gnu-efi/inc/pci22.h new file mode 100644 index 0000000..b94f519 --- /dev/null +++ b/gnu-efi/inc/pci22.h @@ -0,0 +1,193 @@ +#ifndef _PCI22_H +#define _PCI22_H + +/*++ + +Copyright (c) 1999 Intel Corporation + +Module Name: + + pci22.h + +Abstract: + Support for PCI 2.2 standard. + + + + +Revision History + +--*/ + +#ifdef SOFT_SDV +#define PCI_MAX_BUS 1 +#else +#define PCI_MAX_BUS 255 +#endif + +#define PCI_MAX_DEVICE 31 +#define PCI_MAX_FUNC 7 + +// +// Command +// +#define PCI_VGA_PALETTE_SNOOP_DISABLED 0x20 + +#pragma pack(1) +typedef struct { + UINT16 VendorId; + UINT16 DeviceId; + UINT16 Command; + UINT16 Status; + UINT8 RevisionID; + UINT8 ClassCode[3]; + UINT8 CacheLineSize; + UINT8 LaytencyTimer; + UINT8 HeaderType; + UINT8 BIST; +} PCI_DEVICE_INDEPENDENT_REGION; + +typedef struct { + UINT32 Bar[6]; + UINT32 CISPtr; + UINT16 SubsystemVendorID; + UINT16 SubsystemID; + UINT32 ExpansionRomBar; + UINT32 Reserved[2]; + UINT8 InterruptLine; + UINT8 InterruptPin; + UINT8 MinGnt; + UINT8 MaxLat; +} PCI_DEVICE_HEADER_TYPE_REGION; + +typedef struct { + PCI_DEVICE_INDEPENDENT_REGION Hdr; + PCI_DEVICE_HEADER_TYPE_REGION Device; +} PCI_TYPE00; + +typedef struct { + UINT32 Bar[2]; + UINT8 PrimaryBus; + UINT8 SecondaryBus; + UINT8 SubordinateBus; + UINT8 SecondaryLatencyTimer; + UINT8 IoBase; + UINT8 IoLimit; + UINT16 SecondaryStatus; + UINT16 MemoryBase; + UINT16 MemoryLimit; + UINT16 PrefetchableMemoryBase; + UINT16 PrefetchableMemoryLimit; + UINT32 PrefetchableBaseUpper32; + UINT32 PrefetchableLimitUpper32; + UINT16 IoBaseUpper16; + UINT16 IoLimitUpper16; + UINT32 Reserved; + UINT32 ExpansionRomBAR; + UINT8 InterruptLine; + UINT8 InterruptPin; + UINT16 BridgeControl; +} PCI_BRIDGE_CONTROL_REGISTER; + +#define PCI_CLASS_DISPLAY_CTRL 0x03 +#define PCI_CLASS_VGA 0x00 + +#define PCI_CLASS_BRIDGE 0x06 +#define PCI_CLASS_ISA 0x01 +#define PCI_CLASS_ISA_POSITIVE_DECODE 0x80 + +#define PCI_CLASS_NETWORK 0x02 +#define PCI_CLASS_ETHERNET 0x00 + +#define HEADER_TYPE_DEVICE 0x00 +#define HEADER_TYPE_PCI_TO_PCI_BRIDGE 0x01 +#define HEADER_TYPE_MULTI_FUNCTION 0x80 +#define HEADER_LAYOUT_CODE 0x7f + +#define IS_PCI_BRIDGE(_p) ((((_p)->Hdr.HeaderType) & HEADER_LAYOUT_CODE) == HEADER_TYPE_PCI_TO_PCI_BRIDGE) +#define IS_PCI_MULTI_FUNC(_p) (((_p)->Hdr.HeaderType) & HEADER_TYPE_MULTI_FUNCTION) + +typedef struct { + PCI_DEVICE_INDEPENDENT_REGION Hdr; + PCI_BRIDGE_CONTROL_REGISTER Bridge; +} PCI_TYPE01; + +typedef struct { + UINT8 Register; + UINT8 Function; + UINT8 Device; + UINT8 Bus; + UINT8 Reserved[4]; +} DEFIO_PCI_ADDR; + +typedef struct { + UINT32 Reg : 8; + UINT32 Func : 3; + UINT32 Dev : 5; + UINT32 Bus : 8; + UINT32 Reserved: 7; + UINT32 Enable : 1; +} PCI_CONFIG_ACCESS_CF8; + +#pragma pack() + +#define EFI_ROOT_BRIDGE_LIST 'eprb' +typedef struct { + UINTN Signature; + + UINT16 BridgeNumber; + UINT16 PrimaryBus; + UINT16 SubordinateBus; + + EFI_DEVICE_PATH *DevicePath; + + LIST_ENTRY Link; +} PCI_ROOT_BRIDGE_ENTRY; + + +#define PCI_EXPANSION_ROM_HEADER_SIGNATURE 0xaa55 +#define EFI_PCI_EXPANSION_ROM_HEADER_EFISIGNATURE 0x0EF1 +#define PCI_DATA_STRUCTURE_SIGNATURE EFI_SIGNATURE_32('P','C','I','R') + +#pragma pack(1) +typedef struct { + UINT16 Signature; // 0xaa55 + UINT8 Reserved[0x16]; + UINT16 PcirOffset; +} PCI_EXPANSION_ROM_HEADER; + + +typedef struct { + UINT16 Signature; // 0xaa55 + UINT16 InitializationSize; + UINT16 EfiSignature; // 0x0EF1 + UINT16 EfiSubsystem; + UINT16 EfiMachineType; + UINT8 Reserved[0x0A]; + UINT16 EfiImageHeaderOffset; + UINT16 PcirOffset; +} EFI_PCI_EXPANSION_ROM_HEADER; + +typedef struct { + UINT32 Signature; // "PCIR" + UINT16 VendorId; + UINT16 DeviceId; + UINT16 Reserved0; + UINT16 Length; + UINT8 Revision; + UINT8 ClassCode[3]; + UINT16 ImageLength; + UINT16 CodeRevision; + UINT8 CodeType; + UINT8 Indicator; + UINT16 Reserved1; +} PCI_DATA_STRUCTURE; +#pragma pack() + +#endif + + + + + + diff --git a/gnu-efi/inc/protocol/adapterdebug.h b/gnu-efi/inc/protocol/adapterdebug.h new file mode 100644 index 0000000..d70af5d --- /dev/null +++ b/gnu-efi/inc/protocol/adapterdebug.h @@ -0,0 +1,32 @@ +#ifndef _ADAPTER_DEBUG_H +#define _ADAPTER_DEBUG_H + +/*++ + +Copyright (c) 1999 Intel Corporation + +Module Name: + + AdapterDebug.h + +Abstract: + + Protocol to debug the EDD 3.0 enablement of BIOS option ROMs + + + +Revision History + +--*/ + +// {82F86881-282B-11d4-BC7D-0080C73C8881} +#define ADAPTER_DEBUG_PROTOCOL \ +{ 0x82f86881, 0x282b, 0x11d4, {0xbc, 0x7d, 0x0, 0x80, 0xc7, 0x3c, 0x88, 0x81} } + +// +// This protocol points to the BIOS_LEGACY_DRIVE data structure +// see edd.h for more details +// + +#endif + diff --git a/gnu-efi/inc/protocol/eficonsplit.h b/gnu-efi/inc/protocol/eficonsplit.h new file mode 100644 index 0000000..15adb92 --- /dev/null +++ b/gnu-efi/inc/protocol/eficonsplit.h @@ -0,0 +1,32 @@ +#ifndef _EFI_CONFORK_H +#define _EFI_CONFORK_H +/*++ + +Copyright (c) 1999 Intel Corporation + +Module Name: + +Abstract: + + + +Revision History + +--*/ + + + +// +// ConOut Forker Protocol +// + +#define TEXT_OUT_SPLITER_PROTOCOL \ + { 0x56d830a0, 0x7e7a, 0x11d3, {0xbb, 0xa0, 0x0, 0xa0, 0xc9, 0x69, 0x72, 0x3b} } + +#define ERROR_OUT_SPLITER_PROTOCOL \ + { 0xf0ba9039, 0x68f1, 0x425e, {0xaa, 0x7f, 0xd9, 0xaa, 0xf9, 0x1b, 0x82, 0xa1}} + +#define TEXT_IN_SPLITER_PROTOCOL \ + { 0xf9a3c550, 0x7fb5, 0x11d3, {0xbb, 0xa0, 0x0, 0xa0, 0xc9, 0x69, 0x72, 0x3b} } + +#endif diff --git a/gnu-efi/inc/protocol/efidbg.h b/gnu-efi/inc/protocol/efidbg.h new file mode 100644 index 0000000..1f95a70 --- /dev/null +++ b/gnu-efi/inc/protocol/efidbg.h @@ -0,0 +1,210 @@ +/* + * Copyright (c) 1999, 2000 + * Intel Corporation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * + * This product includes software developed by Intel Corporation and + * its contributors. + * + * 4. Neither the name of Intel Corporation or its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY INTEL CORPORATION AND CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL INTEL CORPORATION OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + * + */ + + +#ifndef _EFIDBG_H_ +#define _EFIDBG_H_ + +#include "eficontext.h" +#include "efiser.h" + +typedef struct _DEBUGPORT_16550_CONFIG_DATA { + UINT32 PortAddress; + UINT64 BaudRate; + UINT32 ReceiveFifoDepth; + UINT32 Timeout; + UINT8 Parity; + UINT8 DataBits; + UINT8 StopBits; + UINT32 ControlMask; + BOOLEAN RtsCtsEnable; // RTS, CTS control +} DEBUGPORT_16550_CONFIG_DATA; + +typedef struct _DEBUGPORT_16550_DEVICE_PATH { + EFI_DEVICE_PATH Header; + DEBUGPORT_16550_CONFIG_DATA ConfigData; +} DEBUGPORT_16550_DEVICE_PATH; + +typedef union { + EFI_DEVICE_PATH DevPath; + DEBUGPORT_16550_DEVICE_PATH Uart; + // add new types of debugport device paths to this union... +} DEBUGPORT_DEV_PATH; + + +// +// Debug Support protocol {2755590C-6F3C-42FA-9EA4-A3BA543CDA25} +// + +#define DEBUG_SUPPORT_PROTOCOL \ +{ 0x2755590C, 0x6F3C, 0x42fa, 0x9E, 0xA4, 0xA3, 0xBA, 0x54, 0x3C, 0xDA, 0x25 } + + +typedef UINTN EXCEPTION_TYPE; + +typedef +VOID +(*EXCEPTION_HANDLER) ( + IN EXCEPTION_TYPE ExceptionType, + IN SYSTEM_CONTEXT *SystemContext + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_REGISTER_TIMER_TICK_CALLBACK) ( + IN struct _EFI_DEBUG_SUPPORT_INTERFACE *This, + IN EXCEPTION_HANDLER TimerTickCallback + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_REGISTER_EXCEPTION_HANDLER) ( + IN struct _EFI_DEBUG_SUPPORT_INTERFACE *This, + IN EXCEPTION_HANDLER ExceptionHandler, + IN EXCEPTION_TYPE ExceptionType + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_IP_CALL_TRACE) ( + IN struct _EFI_DEBUG_SUPPORT_INTERFACE *This + ); + + +#define EFI_DEBUG_SUPPORT_INTERFACE_REVISION 0x00010000 + +typedef struct _EFI_DEBUG_SUPPORT_INTERFACE { + UINT32 Revision; + EFI_REGISTER_TIMER_TICK_CALLBACK RegisterTimerTickCallback; + EFI_REGISTER_EXCEPTION_HANDLER RegisterExceptionHandler; + EFI_IP_CALL_TRACE IpCallTrace; +} EFI_DEBUG_SUPPORT_INTERFACE; + + +// +// Debugport io protocol {EBA4E8D2-3858-41EC-A281-2647BA9660D0} +// + +#define DEBUGPORT_IO_PROTOCOL \ +{ 0XEBA4E8D2, 0X3858, 0X41EC, 0XA2, 0X81, 0X26, 0X47, 0XBA, 0X96, 0X60, 0XD0 } + + +typedef +EFI_STATUS +(EFIAPI *EFI_DEBUGPORT_IO_RESET) ( + IN struct _EFI_DEBUGPORT_IO_INTERFACE *This + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_DEBUGPORT_IO_READ) ( + IN struct _EFI_DEBUGPORT_IO_INTERFACE *This, + IN OUT UINTN *BufferSize, + OUT VOID *Buffer + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_DEBUGPORT_IO_WRITE) ( + IN struct _EFI_DEBUGPORT_IO_INTERFACE *This, + IN OUT UINTN *BufferSize, + IN VOID *Buffer + ); + +#define EFI_DEBUGPORT_IO_INTERFACE_REVISION 0x00010000 + +typedef struct _EFI_DEBUGPORT_IO_INTERFACE { + UINT32 Revision; + EFI_DEBUGPORT_IO_READ Read; + EFI_DEBUGPORT_IO_WRITE Write; + EFI_DEBUGPORT_IO_RESET Reset; +} EFI_DEBUGPORT_IO_INTERFACE; + + +// +// Debugport UART16550 control protocol {628EA978-4C26-4605-BC02-A42A496917DD} +// + +#define DEBUGPORT_UART16550_CONTROL_PROTOCOL \ +{ 0X628EA978, 0X4C26, 0X4605, 0XBC, 0X2, 0XA4, 0X2A, 0X49, 0X69, 0X17, 0XDD } + +// Note: The definitions for EFI_PARITY_TYPE, EFI_STOP_BITS_TYPE, and +// SERIAL_IO_MODE are included from efiser.h + +typedef +EFI_STATUS +(EFIAPI *EFI_UART16550_SET_ATTRIBUTES) ( + IN struct _EFI_DEBUGPORT_UART16550_CONTROL_INTERFACE *This, + IN UINT64 BaudRate, + IN UINT32 ReceiveFifoDepth, + IN UINT32 Timeout, + IN EFI_PARITY_TYPE Parity, + IN UINT8 DataBits, + IN EFI_STOP_BITS_TYPE StopBits + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_UART16550_SET_CONTROL_BITS) ( + IN struct _EFI_DEBUGPORT_UART16550_CONTROL_INTERFACE *This, + IN UINT32 Control + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_UART16550_GET_CONTROL_BITS) ( + IN struct _EFI_DEBUGPORT_UART16550_CONTROL_INTERFACE *This, + OUT UINT32 *Control + ); + +#define EFI_DEBUGPORT_UART16550_CONTROL_INTERFACE_REVISION 0x00010000 + +typedef struct _EFI_DEBUGPORT_UART16550_CONTROL_INTERFACE { + UINT32 Revision; + EFI_UART16550_SET_ATTRIBUTES SetAttributes; + EFI_UART16550_SET_CONTROL_BITS SetControl; + EFI_UART16550_GET_CONTROL_BITS GetControl; + DEBUGPORT_16550_CONFIG_DATA *Mode; +} EFI_DEBUGPORT_UART16550_CONTROL_INTERFACE; + + +#define DEVICE_PATH_DEBUGPORT DEBUGPORT_IO_PROTOCOL + +#endif /* _EFIDBG_H_ */ diff --git a/gnu-efi/inc/protocol/efivar.h b/gnu-efi/inc/protocol/efivar.h new file mode 100644 index 0000000..92dc506 --- /dev/null +++ b/gnu-efi/inc/protocol/efivar.h @@ -0,0 +1,133 @@ +/*++ + +Copyright (c) 1998 Intel Corporation + +Module Name: + +Abstract: + + + +Revision History + +--*/ + + + +// +// The variable store protocol interface is specific to the reference +// implementation. The initialization code adds variable store devices +// to the system, and the FW connects to the devices to provide the +// variable store interfaces through these devices. +// + +// +// Variable Store Device protocol +// + +#define VARIABLE_STORE_PROTOCOL \ + { 0xf088cd91, 0xa046, 0x11d2, {0x8e, 0x42, 0x0, 0xa0, 0xc9, 0x69, 0x72, 0x3b} } + +INTERFACE_DECL(_EFI_VARIABLE_STORE); + +typedef +EFI_STATUS +(EFIAPI *EFI_STORE_CLEAR) ( + IN struct _EFI_VARIABLE_STORE *This, + IN UINTN BankNo, + IN OUT VOID *Scratch + ); + + +typedef +EFI_STATUS +(EFIAPI *EFI_STORE_READ) ( + IN struct _EFI_VARIABLE_STORE *This, + IN UINTN BankNo, + IN UINTN Offset, + IN UINTN BufferSize, + OUT VOID *Buffer + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_STORE_UPDATE) ( + IN struct _EFI_VARIABLE_STORE *This, + IN UINTN BankNo, + IN UINTN Offset, + IN UINTN BufferSize, + IN VOID *Buffer + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_STORE_SIZE) ( + IN struct _EFI_VARIABLE_STORE *This, + IN UINTN NoBanks + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_TRANSACTION_UPDATE) ( + IN struct _EFI_VARIABLE_STORE *This, + IN UINTN BankNo, + IN VOID *NewContents + ); + +typedef struct _EFI_VARIABLE_STORE { + + // + // Number of banks and bank size + // + + UINT32 Attributes; + UINT32 BankSize; + UINT32 NoBanks; + + // + // Functions to access the storage banks + // + + EFI_STORE_CLEAR ClearStore; + EFI_STORE_READ ReadStore; + EFI_STORE_UPDATE UpdateStore; + EFI_STORE_SIZE SizeStore OPTIONAL; + EFI_TRANSACTION_UPDATE TransactionUpdate OPTIONAL; + +} EFI_VARIABLE_STORE; + + +// +// +// ClearStore() - A function to clear the requested storage bank. A cleared +// bank contains all "on" bits. +// +// ReadStore() - Read data from the requested store. +// +// UpdateStore() - Updates data on the requested store. The FW will only +// ever issue updates to clear bits in the store. Updates must be +// performed in LSb to MSb order of the update buffer. +// +// SizeStore() - An optional function for non-runtime stores that can be +// dynamically sized. The FW will only ever increase or decrease the store +// by 1 banksize at a time, and it is always adding or removing a bank from +// the end of the store. +// +// By default the FW will update variables and storage banks in an +// "atomic" manner by keeping 1 old copy of the data during an update, +// and recovering appropiately if the power is lost during the middle +// of an operation. To do this the FW needs to have multiple banks +// of storage dedicated to its use. If that's not possible, the driver +// can implement an atomic bank update function and the FW will allow +// 1 bank in this case. (It will allow any number of banks, +// but it won't require an "extra" bank to provide its bank transaction +// function). +// +// TransactionUpdate() - An optional function that can clear & update an +// entire bank in an "atomic" fashion. If the operation fails in the +// middle the driver is responsible for having either the previous copy +// of the bank's data or the new copy. A copy that's partially written +// is not valid as internal data settings may get lost. Supply this +// function only when needed. +// + diff --git a/gnu-efi/inc/protocol/ia64/eficontext.h b/gnu-efi/inc/protocol/ia64/eficontext.h new file mode 100644 index 0000000..1a39a6d --- /dev/null +++ b/gnu-efi/inc/protocol/ia64/eficontext.h @@ -0,0 +1,208 @@ +/* + * Copyright (c) 1999, 2000 + * Intel Corporation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * + * This product includes software developed by Intel Corporation and + * its contributors. + * + * 4. Neither the name of Intel Corporation or its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY INTEL CORPORATION AND CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL INTEL CORPORATION OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + * + */ + + +#ifndef _EFICONTEXT_H_ +#define _EFICONTEXT_H_ + + +// +// IA-64 processor exception types +// +#define EXCPT_ALT_DTLB 4 +#define EXCPT_DNESTED_TLB 5 +#define EXCPT_BREAKPOINT 11 +#define EXCPT_EXTERNAL_INTERRUPT 12 +#define EXCPT_GEN_EXCEPT 24 +#define EXCPT_NAT_CONSUMPTION 26 +#define EXCPT_DEBUG_EXCEPT 29 +#define EXCPT_UNALIGNED_ACCESS 30 +#define EXCPT_FP_FAULT 32 +#define EXCPT_FP_TRAP 33 +#define EXCPT_TAKEN_BRANCH 35 +#define EXCPT_SINGLE_STEP 36 + +// +// IA-64 processor context definition - must be 512 byte aligned!!! +// +typedef +struct { + UINT64 reserved; // necessary to preserve alignment for the correct bits in UNAT and to insure F2 is 16 byte aligned... + + UINT64 r1; + UINT64 r2; + UINT64 r3; + UINT64 r4; + UINT64 r5; + UINT64 r6; + UINT64 r7; + UINT64 r8; + UINT64 r9; + UINT64 r10; + UINT64 r11; + UINT64 r12; + UINT64 r13; + UINT64 r14; + UINT64 r15; + UINT64 r16; + UINT64 r17; + UINT64 r18; + UINT64 r19; + UINT64 r20; + UINT64 r21; + UINT64 r22; + UINT64 r23; + UINT64 r24; + UINT64 r25; + UINT64 r26; + UINT64 r27; + UINT64 r28; + UINT64 r29; + UINT64 r30; + UINT64 r31; + + UINT64 f2[2]; + UINT64 f3[2]; + UINT64 f4[2]; + UINT64 f5[2]; + UINT64 f6[2]; + UINT64 f7[2]; + UINT64 f8[2]; + UINT64 f9[2]; + UINT64 f10[2]; + UINT64 f11[2]; + UINT64 f12[2]; + UINT64 f13[2]; + UINT64 f14[2]; + UINT64 f15[2]; + UINT64 f16[2]; + UINT64 f17[2]; + UINT64 f18[2]; + UINT64 f19[2]; + UINT64 f20[2]; + UINT64 f21[2]; + UINT64 f22[2]; + UINT64 f23[2]; + UINT64 f24[2]; + UINT64 f25[2]; + UINT64 f26[2]; + UINT64 f27[2]; + UINT64 f28[2]; + UINT64 f29[2]; + UINT64 f30[2]; + UINT64 f31[2]; + + UINT64 pr; + + UINT64 b0; + UINT64 b1; + UINT64 b2; + UINT64 b3; + UINT64 b4; + UINT64 b5; + UINT64 b6; + UINT64 b7; + + // application registers + UINT64 ar_rsc; + UINT64 ar_bsp; + UINT64 ar_bspstore; + UINT64 ar_rnat; + + UINT64 ar_fcr; + + UINT64 ar_eflag; + UINT64 ar_csd; + UINT64 ar_ssd; + UINT64 ar_cflg; + UINT64 ar_fsr; + UINT64 ar_fir; + UINT64 ar_fdr; + + UINT64 ar_ccv; + + UINT64 ar_unat; + + UINT64 ar_fpsr; + + UINT64 ar_pfs; + UINT64 ar_lc; + UINT64 ar_ec; + + // control registers + UINT64 cr_dcr; + UINT64 cr_itm; + UINT64 cr_iva; + UINT64 cr_pta; + UINT64 cr_ipsr; + UINT64 cr_isr; + UINT64 cr_iip; + UINT64 cr_ifa; + UINT64 cr_itir; + UINT64 cr_iipa; + UINT64 cr_ifs; + UINT64 cr_iim; + UINT64 cr_iha; + + // debug registers + UINT64 dbr0; + UINT64 dbr1; + UINT64 dbr2; + UINT64 dbr3; + UINT64 dbr4; + UINT64 dbr5; + UINT64 dbr6; + UINT64 dbr7; + + UINT64 ibr0; + UINT64 ibr1; + UINT64 ibr2; + UINT64 ibr3; + UINT64 ibr4; + UINT64 ibr5; + UINT64 ibr6; + UINT64 ibr7; + + // virtual registers + UINT64 int_nat; // nat bits for R1-R31 + +} SYSTEM_CONTEXT; + +#endif /* _EFI_CONTEXT_H_ */ diff --git a/gnu-efi/inc/protocol/intload.h b/gnu-efi/inc/protocol/intload.h new file mode 100644 index 0000000..fb24e3f --- /dev/null +++ b/gnu-efi/inc/protocol/intload.h @@ -0,0 +1,27 @@ +/*++ + +Copyright (c) 1999 Intel Corporation + +Module Name: + + intload + +Abstract: + + EFI support for loading internally linked in apps + + + +Revision History + +--*/ + +#ifndef _INTERNAL_LOAD_INCLUDE_ +#define _INTERNAL_LOAD_INCLUDE_ + +// {D65A6B8C-71E5-4df0-A909-F0D2992B5AA9} +#define INTERNAL_SHELL_GUID \ + { 0xd65a6b8c, 0x71e5, 0x4df0, {0xa9, 0x09, 0xf0, 0xd2, 0x99, 0x2b, 0x5a, 0xa9} } + + +#endif diff --git a/gnu-efi/inc/protocol/legacyboot.h b/gnu-efi/inc/protocol/legacyboot.h new file mode 100644 index 0000000..16e94e7 --- /dev/null +++ b/gnu-efi/inc/protocol/legacyboot.h @@ -0,0 +1,119 @@ +/*++ + +Copyright (c) 1999 Intel Corporation + +Module Name: + + legacyboot + +Abstract: + + EFI support for legacy boot + + + +Revision History + +--*/ + +#ifndef _LEGACY_BOOT_INCLUDE_ +#define _LEGACY_BOOT_INCLUDE_ + +#define LEGACY_BOOT_PROTOCOL \ + { 0x376e5eb2, 0x30e4, 0x11d3, { 0xba, 0xe5, 0x0, 0x80, 0xc7, 0x3c, 0x88, 0x81 } } + +#pragma pack(1) + +// +// BBS 1.01 (See Appendix A) IPL and BCV Table Entry Data structure. +// Seg:Off pointers have been converted to EFI pointers in this data structure +// This is the structure that also maps to the EFI device path for the boot selection +// +typedef struct { + UINT16 DeviceType; + UINT16 StatusFlag; + UINT32 Reserved; + VOID *BootHandler; // Not an EFI entry point + CHAR8 *DescString; +} BBS_TABLE_ENTRY; +#pragma pack() + +typedef +EFI_STATUS +(EFIAPI *LEGACY_BOOT_CALL) ( + IN EFI_DEVICE_PATH *DevicePath + ); + + +// +// BBS support functions +// PnP Call numbers and BiosSelector hidden in implementation +// + +typedef enum { + IplRelative, + BcvRelative +} BBS_TYPE; + +INTERFACE_DECL(_LEGACY_BOOT_INTERFACE); + +// +// == PnP Function 0x60 then BbsVersion == 0x0101 if this call fails then BbsVersion == 0x0000 +// + +// +// == PnP Function 0x61 +// +typedef +EFI_STATUS +(EFIAPI *GET_DEVICE_COUNT) ( + IN struct _LEGACY_BOOT_INTERFACE *This, + IN BBS_TYPE *TableType, + OUT UINTN *DeviceCount, + OUT UINTN *MaxCount + ); + +// +// == PnP Function 0x62 +// +typedef +EFI_STATUS +(EFIAPI *GET_PRIORITY_AND_TABLE) ( + IN struct _LEGACY_BOOT_INTERFACE *This, + IN BBS_TYPE *TableType, + IN OUT UINTN *PrioritySize, // MaxCount * sizeof(UINT8) + OUT UINTN *Priority, + IN OUT UINTN *TableSize, // MaxCount * sizeof(BBS_TABLE_ENTRY) + OUT BBS_TABLE_ENTRY *TableEntrySize + ); + +// +// == PnP Function 0x63 +// +typedef +EFI_STATUS +(EFIAPI *SET_PRIORITY) ( + IN struct _LEGACY_BOOT_INTERFACE *This, + IN BBS_TYPE *TableType, + IN OUT UINTN *PrioritySize, + OUT UINTN *Priority + ); + +typedef struct _LEGACY_BOOT_INTERFACE { + LEGACY_BOOT_CALL BootIt; + + // + // New functions to allow BBS booting to be configured from EFI + // + UINTN BbsVersion; // Currently 0x0101 + GET_DEVICE_COUNT GetDeviceCount; + GET_PRIORITY_AND_TABLE GetPriorityAndTable; + SET_PRIORITY SetPriority; +} LEGACY_BOOT_INTERFACE; + +EFI_STATUS +PlInitializeLegacyBoot ( + VOID + ); + +#endif diff --git a/gnu-efi/inc/protocol/make.inf b/gnu-efi/inc/protocol/make.inf new file mode 100644 index 0000000..f3bb907 --- /dev/null +++ b/gnu-efi/inc/protocol/make.inf @@ -0,0 +1,13 @@ +# +# +# + +[sources] + efivar.h + legacyboot.h + VgaClass.h + intload.h + +[ia32sources] + +[ia64sources] diff --git a/gnu-efi/inc/protocol/makefile.hdr b/gnu-efi/inc/protocol/makefile.hdr new file mode 100644 index 0000000..118d6ba --- /dev/null +++ b/gnu-efi/inc/protocol/makefile.hdr @@ -0,0 +1,29 @@ + +# +# This is a machine generated file - DO NOT EDIT +# Generated by genmake.exe +# Generated from make.inf +# Copyright (c) 1998 Intel Corporation +# + +INC_DEPS = $(INC_DEPS) \ + $(SDK_INSTALL_DIR)\include\efi\protocol\efivar.h \ + $(SDK_INSTALL_DIR)\include\efi\protocol\legacyboot.h \ + $(SDK_INSTALL_DIR)\include\efi\protocol\vgaclass.h \ + $(SDK_INSTALL_DIR)\include\efi\protocol\efidbg.h \ + + +!IF "$(PROCESSOR)" == "Ia32" +INC_DEPS = $(INC_DEPS) \ + + +!ENDIF + + +!IF "$(PROCESSOR)" == "Ia64" +INC_DEPS = $(INC_DEPS) \ + $(SDK_INSTALL_DIR)\include\efi\protocol\$(PROCESSOR)\eficontext.h \ + + +!ENDIF + diff --git a/gnu-efi/inc/protocol/piflash64.h b/gnu-efi/inc/protocol/piflash64.h new file mode 100644 index 0000000..d521dfc --- /dev/null +++ b/gnu-efi/inc/protocol/piflash64.h @@ -0,0 +1,121 @@ +#ifndef _PIFLASH64_H +#define _PIFLASH64_H + +/*++ + +Copyright (c) 1999 Intel Corporation + +Module Name: + + PIflash64.h + +Abstract: + + Iflash64.efi protocol to abstract iflash from + the system. + +Revision History + +--*/ + +// +// Guid that identifies the IFLASH protocol +// +#define IFLASH64_PROTOCOL_PROTOCOL \ + { 0x65cba110, 0x74ab, 0x11d3, 0xbb, 0x89, 0x0, 0x80, 0xc7, 0x3c, 0x88, 0x81 }; + +// +// Unlock FLASH from StartAddress to EndAddress and return a LockKey +// +typedef +EFI_STATUS +(EFIAPI *UNLOCK_FLASH_API)( + IN struct _IFLASH64_PROTOCOL_INTERFACE *This + ); + +// +// Lock the flash represented by the LockKey +// +typedef +EFI_STATUS +(EFIAPI *LOCK_FLASH_API)( + IN struct _IFLASH64_PROTOCOL_INTERFACE *This + ); + +// +// Status callback for a utility like IFLASH64 +// +// Token would map to a list like Ted proposed. The utility has no idea what +// happens on the other side. +// ErrorStatus - Level of Error or success. Independent of Token. If you +// don't know the token you will at least know pass or fail. +// String - Optional extra information about the error. Could be used for +// debug or future expansion +// +// Attributes - Options screen attributes for String. Could allow the string to be different colors. +// +typedef +EFI_STATUS +(EFIAPI *UTILITY_PROGRESS_API)( + IN struct _IFLASH64_PROTOCOL_INTERFACE *This, + IN UINTN Token, + IN EFI_STATUS ErrorStatus, + IN CHAR16 *String, OPTIONAL + IN UINTN *Attributes OPTIONAL + ); + +// +// Token Values +// +// IFlash64 Token Codes +#define IFLASH_TOKEN_IFLASHSTART 0xB0 // IFlash64 has started +#define IFLASH_TOKEN_READINGFILE 0xB1 // Reading File +#define IFLASH_TOKEN_INITVPP 0xB2 // Initializing Vpp +#define IFLASH_TOKEN_DISABLEVPP 0x10 // Disable Vpp +#define IFLASH_TOKEN_FLASHUNLOCK 0xB3 // Unlocking FLASH Devices +#define IFLASH_TOKEN_FLASHERASE 0xB4 // Erasing FLASH Devices +#define IFLASH_TOKEN_FLASHPROGRAM 0xB5 // Programming FLASH +#define IFLASH_TOKEN_FLASHVERIFY 0xB6 // Verifying FLASH +#define IFLASH_TOKEN_UPDATESUCCES 0xB7 // FLASH Updage Success! + +#define IFLASH_TOKEN_PROGRESS_READINGFILE 0x11 // % Reading File +#define IFLASH_TOKEN_PROGRESS_FLASHUNLOCK 0x13 // % Unlocking FLASH Devices +#define IFLASH_TOKEN_PROGRESS_FLASHERASE 0x14 // % Erasing FLASH Devices +#define IFLASH_TOKEN_PROGRESS_FLASHPROGRAM 0x15 // % Programming FLASH +#define IFLASH_TOKEN_PROGRESS_FLASHVERIFY 0x16 // % Verifying FLASH + +#define IFLASH_TOKEN_READINGFILE_ER 0xB8 // File Read Error +#define IFLASH_TOKEN_INITVPP_ER 0xB9 // Initialization of IFB Error +#define IFLASH_TOKEN_FLASHUNLOCK_ER 0xBA // FLASH Unlock Error +#define IFLASH_TOKEN_FLASHERASE_ER 0xBB // FLASH Erase Error +#define IFLASH_TOKEN_FLASHVERIFY_ER 0xBC // FLASH Verify Error +#define IFLASH_TOKEN_FLASHPROG_ER 0xBD // FLASH Program Error + +#define IFLASH_TABLE_END 0x00 + +// +// If this number changes one of the existing API's has changes +// +#define IFLASH_PI_MAJOR_VERSION 0x01 + +// +// This number changes when new APIs or data variables get added to the end +// of the data structure +// +#define IFLASH_PI_MINOR_VERSION 0x01 + +typedef struct _IFLASH64_PROTOCOL_INTERFACE { + UINT32 MajorVersion; + UINT32 MinorVersion; + UNLOCK_FLASH_API UnlockFlash; + LOCK_FLASH_API LockFlash; + UTILITY_PROGRESS_API Progress; + + // + // Future expansion goes here + // + +} IFLASH64_PROTOCOL_INTERFACE; + + +#endif diff --git a/gnu-efi/inc/protocol/readme.txt b/gnu-efi/inc/protocol/readme.txt new file mode 100644 index 0000000..66e155c --- /dev/null +++ b/gnu-efi/inc/protocol/readme.txt @@ -0,0 +1,3 @@ +The protocol directory contains non Architectural +Protocols that span the FW, Platform, or application +space. \ No newline at end of file diff --git a/gnu-efi/inc/protocol/vgaclass.h b/gnu-efi/inc/protocol/vgaclass.h new file mode 100644 index 0000000..d0deb5c --- /dev/null +++ b/gnu-efi/inc/protocol/vgaclass.h @@ -0,0 +1,95 @@ +#ifndef _VGA_CLASS_H +#define _VGA_CLASS_H + +/*++ + +Copyright (c) 1999 Intel Corporation + +Module Name: + + VgaClass.h + +Abstract: + + Vga Mini port binding to Vga Class protocol + + + +Revision History + +--*/ + +// +// VGA Device Structure +// + +// {0E3D6310-6FE4-11d3-BB81-0080C73C8881} +#define VGA_CLASS_DRIVER_PROTOCOL \ + { 0xe3d6310, 0x6fe4, 0x11d3, {0xbb, 0x81, 0x0, 0x80, 0xc7, 0x3c, 0x88, 0x81} } + +typedef +EFI_STATUS +(* INIT_VGA_CARD) ( + IN UINTN VgaMode, + IN VOID *Context + ); + +typedef struct { + UINTN MaxColumns; + UINTN MaxRows; +} MAX_CONSOLE_GEOMETRY; + +#define VGA_CON_OUT_DEV_SIGNATURE EFI_SIGNATURE_32('c','v','g','a') +typedef struct { + UINTN Signature; + + EFI_HANDLE Handle; + SIMPLE_TEXT_OUTPUT_INTERFACE ConOut; + SIMPLE_TEXT_OUTPUT_MODE ConOutMode; + EFI_DEVICE_PATH *DevicePath; + + UINT8 *Buffer; + EFI_DEVICE_IO_INTERFACE *DeviceIo; + + // + // Video Card Context + // + INIT_VGA_CARD InitVgaCard; + VOID *VgaCardContext; + MAX_CONSOLE_GEOMETRY *Geometry; + // + // Video buffer normally 0xb8000 + // + UINT64 VideoBuffer; + + // + // Clear Screen & Default Attribute + // + UINT32 Attribute; + + // + // -1 means search for active VGA device + // + EFI_PCI_ADDRESS_UNION Pci; +} VGA_CON_OUT_DEV; + +#define VGA_CON_OUT_DEV_FROM_THIS(a) CR(a, VGA_CON_OUT_DEV, ConOut, VGA_CON_OUT_DEV_SIGNATURE) + +// +// Vga Class Driver Protocol. +// GUID defined in EFI Lib +// + +typedef +EFI_STATUS +(EFIAPI *INSTALL_VGA_DRIVER) ( + IN VGA_CON_OUT_DEV *ConOutDev + ); + +typedef struct { + UINT32 Version; + INSTALL_VGA_DRIVER InstallGenericVgaDriver; +} INSTALL_VGA_DRIVER_INTERFACE; + +#endif + diff --git a/gnu-efi/inc/romload.h b/gnu-efi/inc/romload.h new file mode 100644 index 0000000..0506011 --- /dev/null +++ b/gnu-efi/inc/romload.h @@ -0,0 +1,41 @@ +#ifndef _EFI_ROMLOAD_H +#define _EFI_ROMLOAD_H + +#define ROM_SIGNATURE 0xaa55 +#define PCIDS_SIGNATURE "PCIR" +#pragma pack(push) +#pragma pack(1) +typedef struct +{ + UINT8 Pcids_Sig[4]; + UINT16 VendId; + UINT16 DevId; + UINT16 Vpd_Off; + UINT16 Size; + UINT8 Rev; + UINT8 Class_Code[3]; + UINT16 Image_Len; + UINT16 Rev_Lvl; + UINT8 Code_Type; + UINT8 Indi; + UINT16 Rsvd; +}PciDataStructure; +typedef struct +{ + UINT16 Size; + UINT32 Header_Sig; + UINT16 SubSystem; + UINT16 MachineType; + UINT8 Resvd[10]; + UINT16 EfiOffset; +}ArchData; +typedef struct +{ + UINT16 Rom_Sig; + ArchData Arch_Data; + UINT16 Pcids_Off; + UINT8 resvd[38]; +}RomHeader; +#pragma pack(pop) + +#endif diff --git a/gnu-efi/inc/x86_64/efibind.h b/gnu-efi/inc/x86_64/efibind.h new file mode 100644 index 0000000..31e9e11 --- /dev/null +++ b/gnu-efi/inc/x86_64/efibind.h @@ -0,0 +1,392 @@ +/*++ + +Copyright (c) 1998 Intel Corporation + +Module Name: + + efefind.h + +Abstract: + + EFI to compile bindings + + + + +Revision History + +--*/ +#ifndef X86_64_EFI_BIND +#define X86_64_EFI_BIND +#ifndef __GNUC__ +#pragma pack() +#endif + +#if defined(GNU_EFI_USE_MS_ABI) + #if (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 7)))||(defined(__clang__) && (__clang_major__ > 3 || (__clang_major__ == 3 && __clang_minor__ >= 2))) + #define HAVE_USE_MS_ABI 1 + #else + #error Compiler is too old for GNU_EFI_USE_MS_ABI + #endif +#endif + +// +// Basic int types of various widths +// + +#if !defined(__STDC_VERSION__) || (__STDC_VERSION__ < 199901L ) && !defined(__cplusplus) + + // No ANSI C 1999/2000 stdint.h integer width declarations + + #if defined(_MSC_EXTENSIONS) + + // Use Microsoft C compiler integer width declarations + + typedef unsigned __int64 uint64_t; + typedef __int64 int64_t; + typedef unsigned __int32 uint32_t; + typedef __int32 int32_t; + typedef unsigned short uint16_t; + typedef short int16_t; + typedef unsigned char uint8_t; + typedef char int8_t; + #elif defined(__GNUC__) + typedef int __attribute__((__mode__(__DI__))) int64_t; + typedef unsigned int __attribute__((__mode__(__DI__))) uint64_t; + typedef unsigned int uint32_t; + typedef int int32_t; + typedef unsigned short uint16_t; + typedef short int16_t; + typedef unsigned char uint8_t; + typedef signed char int8_t; + #elif defined(UNIX_LP64) + + /* Use LP64 programming model from C_FLAGS for integer width declarations */ + + typedef unsigned long uint64_t; + typedef long int64_t; + typedef unsigned int uint32_t; + typedef int int32_t; + typedef unsigned short uint16_t; + typedef short int16_t; + typedef unsigned char uint8_t; + typedef char int8_t; + #else + + /* Assume P64 programming model from C_FLAGS for integer width declarations */ + + typedef unsigned long long uint64_t __attribute__((aligned (8))); + typedef long long int64_t __attribute__((aligned (8))); + typedef unsigned int uint32_t; + typedef int int32_t; + typedef unsigned short uint16_t; + typedef short int16_t; + typedef unsigned char uint8_t; + typedef char int8_t; + #endif + typedef uint64_t uintptr_t; + typedef int64_t intptr_t; +#else + #include +#endif + +// +// Basic EFI types of various widths +// + +#ifndef __WCHAR_TYPE__ +# define __WCHAR_TYPE__ short +#endif + +typedef uint64_t UINT64; +typedef int64_t INT64; + +#ifndef _BASETSD_H_ + typedef uint32_t UINT32; + typedef int32_t INT32; +#endif + +typedef uint16_t UINT16; +typedef int16_t INT16; +typedef uint8_t UINT8; +typedef int8_t INT8; +typedef __WCHAR_TYPE__ WCHAR; + +#undef VOID +#define VOID void + + +typedef int64_t INTN; +typedef uint64_t UINTN; + +#ifdef EFI_NT_EMULATOR + #define POST_CODE(_Data) +#else + #ifdef EFI_DEBUG +#define POST_CODE(_Data) __asm mov eax,(_Data) __asm out 0x80,al + #else + #define POST_CODE(_Data) + #endif +#endif + +#define EFIERR(a) (0x8000000000000000 | a) +#define EFI_ERROR_MASK 0x8000000000000000 +#define EFIERR_OEM(a) (0xc000000000000000 | a) + + +#define BAD_POINTER 0xFBFBFBFBFBFBFBFB +#define MAX_ADDRESS 0xFFFFFFFFFFFFFFFF + +#ifdef EFI_NT_EMULATOR + #define BREAKPOINT() __asm { int 3 } +#else + #define BREAKPOINT() while (TRUE); // Make it hang on Bios[Dbg]32 +#endif + +// +// Pointers must be aligned to these address to function +// + +#define MIN_ALIGNMENT_SIZE 4 + +#define ALIGN_VARIABLE(Value ,Adjustment) \ + (UINTN)Adjustment = 0; \ + if((UINTN)Value % MIN_ALIGNMENT_SIZE) \ + (UINTN)Adjustment = MIN_ALIGNMENT_SIZE - ((UINTN)Value % MIN_ALIGNMENT_SIZE); \ + Value = (UINTN)Value + (UINTN)Adjustment + + +// +// Define macros to build data structure signatures from characters. +// + +#define EFI_SIGNATURE_16(A,B) ((A) | (B<<8)) +#define EFI_SIGNATURE_32(A,B,C,D) (EFI_SIGNATURE_16(A,B) | (EFI_SIGNATURE_16(C,D) << 16)) +#define EFI_SIGNATURE_64(A,B,C,D,E,F,G,H) (EFI_SIGNATURE_32(A,B,C,D) | ((UINT64)(EFI_SIGNATURE_32(E,F,G,H)) << 32)) +// +// To export & import functions in the EFI emulator environment +// + +#ifdef EFI_NT_EMULATOR + #define EXPORTAPI __declspec( dllexport ) +#else + #define EXPORTAPI +#endif + + +// +// EFIAPI - prototype calling convention for EFI function pointers +// BOOTSERVICE - prototype for implementation of a boot service interface +// RUNTIMESERVICE - prototype for implementation of a runtime service interface +// RUNTIMEFUNCTION - prototype for implementation of a runtime function that is not a service +// RUNTIME_CODE - pragma macro for declaring runtime code +// + +#ifndef EFIAPI // Forces EFI calling conventions reguardless of compiler options + #ifdef _MSC_EXTENSIONS + #define EFIAPI __cdecl // Force C calling convention for Microsoft C compiler + #elif defined(HAVE_USE_MS_ABI) + // Force amd64/ms calling conventions. + #define EFIAPI __attribute__((ms_abi)) + #else + #define EFIAPI // Substitute expresion to force C calling convention + #endif +#endif + +#define BOOTSERVICE +//#define RUNTIMESERVICE(proto,a) alloc_text("rtcode",a); proto a +//#define RUNTIMEFUNCTION(proto,a) alloc_text("rtcode",a); proto a +#define RUNTIMESERVICE +#define RUNTIMEFUNCTION + + +#define RUNTIME_CODE(a) alloc_text("rtcode", a) +#define BEGIN_RUNTIME_DATA() data_seg("rtdata") +#define END_RUNTIME_DATA() data_seg("") + +#define VOLATILE volatile + +#define MEMORY_FENCE() + +#ifdef EFI_NT_EMULATOR + +// +// To help ensure proper coding of integrated drivers, they are +// compiled as DLLs. In NT they require a dll init entry pointer. +// The macro puts a stub entry point into the DLL so it will load. +// + +#define EFI_DRIVER_ENTRY_POINT(InitFunction) \ + UINTN \ + __stdcall \ + _DllMainCRTStartup ( \ + UINTN Inst, \ + UINTN reason_for_call, \ + VOID *rserved \ + ) \ + { \ + return 1; \ + } \ + \ + int \ + EXPORTAPI \ + __cdecl \ + InitializeDriver ( \ + void *ImageHandle, \ + void *SystemTable \ + ) \ + { \ + return InitFunction(ImageHandle, SystemTable); \ + } + + + #define LOAD_INTERNAL_DRIVER(_if, type, name, entry) \ + (_if)->LoadInternal(type, name, NULL) + +#else // EFI_NT_EMULATOR + +// +// When build similiar to FW, then link everything together as +// one big module. For the MSVC toolchain, we simply tell the +// linker what our driver init function is using /ENTRY. +// +#if defined(_MSC_EXTENSIONS) + #define EFI_DRIVER_ENTRY_POINT(InitFunction) \ + __pragma(comment(linker, "/ENTRY:" # InitFunction)) +#else + #define EFI_DRIVER_ENTRY_POINT(InitFunction) \ + UINTN \ + InitializeDriver ( \ + VOID *ImageHandle, \ + VOID *SystemTable \ + ) \ + { \ + return InitFunction(ImageHandle, \ + SystemTable); \ + } \ + \ + EFI_STATUS efi_main( \ + EFI_HANDLE image, \ + EFI_SYSTEM_TABLE *systab \ + ) __attribute__((weak, \ + alias ("InitializeDriver"))); +#endif + + #define LOAD_INTERNAL_DRIVER(_if, type, name, entry) \ + (_if)->LoadInternal(type, name, entry) + +#endif // EFI_NT_EMULATOR + +// +// Some compilers don't support the forward reference construct: +// typedef struct XXXXX +// +// The following macro provide a workaround for such cases. +// +#ifdef NO_INTERFACE_DECL +#define INTERFACE_DECL(x) +#else +#if defined(__GNUC__) || defined(_MSC_EXTENSIONS) +#define INTERFACE_DECL(x) struct x +#else +#define INTERFACE_DECL(x) typedef struct x +#endif +#endif + +/* for x86_64, EFI_FUNCTION_WRAPPER must be defined */ +#if defined(HAVE_USE_MS_ABI) +#define uefi_call_wrapper(func, va_num, ...) func(__VA_ARGS__) +#else +/* + Credits for macro-magic: + https://groups.google.com/forum/?fromgroups#!topic/comp.std.c/d-6Mj5Lko_s + http://efesx.com/2010/08/31/overloading-macros/ +*/ +#define __VA_NARG__(...) \ + __VA_NARG_(_0, ## __VA_ARGS__, __RSEQ_N()) +#define __VA_NARG_(...) \ + __VA_ARG_N(__VA_ARGS__) +#define __VA_ARG_N( \ + _0,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,N,...) N +#define __RSEQ_N() \ + 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 + +#define __VA_ARG_NSUFFIX__(prefix,...) \ + __VA_ARG_NSUFFIX_N(prefix, __VA_NARG__(__VA_ARGS__)) +#define __VA_ARG_NSUFFIX_N(prefix,nargs) \ + __VA_ARG_NSUFFIX_N_(prefix, nargs) +#define __VA_ARG_NSUFFIX_N_(prefix,nargs) \ + prefix ## nargs + +/* Prototypes of EFI cdecl -> stdcall trampolines */ +UINT64 efi_call0(void *func); +UINT64 efi_call1(void *func, UINT64 arg1); +UINT64 efi_call2(void *func, UINT64 arg1, UINT64 arg2); +UINT64 efi_call3(void *func, UINT64 arg1, UINT64 arg2, UINT64 arg3); +UINT64 efi_call4(void *func, UINT64 arg1, UINT64 arg2, UINT64 arg3, + UINT64 arg4); +UINT64 efi_call5(void *func, UINT64 arg1, UINT64 arg2, UINT64 arg3, + UINT64 arg4, UINT64 arg5); +UINT64 efi_call6(void *func, UINT64 arg1, UINT64 arg2, UINT64 arg3, + UINT64 arg4, UINT64 arg5, UINT64 arg6); +UINT64 efi_call7(void *func, UINT64 arg1, UINT64 arg2, UINT64 arg3, + UINT64 arg4, UINT64 arg5, UINT64 arg6, UINT64 arg7); +UINT64 efi_call8(void *func, UINT64 arg1, UINT64 arg2, UINT64 arg3, + UINT64 arg4, UINT64 arg5, UINT64 arg6, UINT64 arg7, + UINT64 arg8); +UINT64 efi_call9(void *func, UINT64 arg1, UINT64 arg2, UINT64 arg3, + UINT64 arg4, UINT64 arg5, UINT64 arg6, UINT64 arg7, + UINT64 arg8, UINT64 arg9); +UINT64 efi_call10(void *func, UINT64 arg1, UINT64 arg2, UINT64 arg3, + UINT64 arg4, UINT64 arg5, UINT64 arg6, UINT64 arg7, + UINT64 arg8, UINT64 arg9, UINT64 arg10); + +/* Front-ends to efi_callX to avoid compiler warnings */ +#define _cast64_efi_call0(f) \ + efi_call0(f) +#define _cast64_efi_call1(f,a1) \ + efi_call1(f, (UINT64)(a1)) +#define _cast64_efi_call2(f,a1,a2) \ + efi_call2(f, (UINT64)(a1), (UINT64)(a2)) +#define _cast64_efi_call3(f,a1,a2,a3) \ + efi_call3(f, (UINT64)(a1), (UINT64)(a2), (UINT64)(a3)) +#define _cast64_efi_call4(f,a1,a2,a3,a4) \ + efi_call4(f, (UINT64)(a1), (UINT64)(a2), (UINT64)(a3), (UINT64)(a4)) +#define _cast64_efi_call5(f,a1,a2,a3,a4,a5) \ + efi_call5(f, (UINT64)(a1), (UINT64)(a2), (UINT64)(a3), (UINT64)(a4), \ + (UINT64)(a5)) +#define _cast64_efi_call6(f,a1,a2,a3,a4,a5,a6) \ + efi_call6(f, (UINT64)(a1), (UINT64)(a2), (UINT64)(a3), (UINT64)(a4), \ + (UINT64)(a5), (UINT64)(a6)) +#define _cast64_efi_call7(f,a1,a2,a3,a4,a5,a6,a7) \ + efi_call7(f, (UINT64)(a1), (UINT64)(a2), (UINT64)(a3), (UINT64)(a4), \ + (UINT64)(a5), (UINT64)(a6), (UINT64)(a7)) +#define _cast64_efi_call8(f,a1,a2,a3,a4,a5,a6,a7,a8) \ + efi_call8(f, (UINT64)(a1), (UINT64)(a2), (UINT64)(a3), (UINT64)(a4), \ + (UINT64)(a5), (UINT64)(a6), (UINT64)(a7), (UINT64)(a8)) +#define _cast64_efi_call9(f,a1,a2,a3,a4,a5,a6,a7,a8,a9) \ + efi_call9(f, (UINT64)(a1), (UINT64)(a2), (UINT64)(a3), (UINT64)(a4), \ + (UINT64)(a5), (UINT64)(a6), (UINT64)(a7), (UINT64)(a8), \ + (UINT64)(a9)) +#define _cast64_efi_call10(f,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10) \ + efi_call10(f, (UINT64)(a1), (UINT64)(a2), (UINT64)(a3), (UINT64)(a4), \ + (UINT64)(a5), (UINT64)(a6), (UINT64)(a7), (UINT64)(a8), \ + (UINT64)(a9), (UINT64)(a10)) + +/* main wrapper (va_num ignored) */ +#define uefi_call_wrapper(func,va_num,...) \ + __VA_ARG_NSUFFIX__(_cast64_efi_call, __VA_ARGS__) (func , ##__VA_ARGS__) + +#endif + +#if defined(HAVE_USE_MS_ABI) && !defined(_MSC_EXTENSIONS) + #define EFI_FUNCTION __attribute__((ms_abi)) +#else + #define EFI_FUNCTION +#endif + +#ifdef _MSC_EXTENSIONS +#pragma warning ( disable : 4731 ) // Suppress warnings about modification of EBP +#endif + +#endif diff --git a/gnu-efi/inc/x86_64/efilibplat.h b/gnu-efi/inc/x86_64/efilibplat.h new file mode 100644 index 0000000..3844578 --- /dev/null +++ b/gnu-efi/inc/x86_64/efilibplat.h @@ -0,0 +1,26 @@ +/*++ + +Copyright (c) 1998 Intel Corporation + +Module Name: + + efilibplat.h + +Abstract: + + EFI to compile bindings + + + + +Revision History + +--*/ + +VOID +InitializeLibPlatform ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + + diff --git a/gnu-efi/inc/x86_64/efisetjmp_arch.h b/gnu-efi/inc/x86_64/efisetjmp_arch.h new file mode 100644 index 0000000..b1ad1fe --- /dev/null +++ b/gnu-efi/inc/x86_64/efisetjmp_arch.h @@ -0,0 +1,22 @@ +#ifndef GNU_EFI_X86_64_SETJMP_H +#define GNU_EFI_X86_64_SETJMP_H + +#define JMPBUF_ALIGN 8 + +typedef struct { + UINT64 Rbx; + UINT64 Rsp; + UINT64 Rbp; + + UINT64 Rdi; + UINT64 Rsi; + UINT64 R12; + UINT64 R13; + UINT64 R14; + UINT64 R15; + UINT64 Rip; + UINT64 MxCsr; + UINT8 XmmBuffer[160]; // XMM6 - XMM15 +} ALIGN(JMPBUF_ALIGN) jmp_buf[1]; + +#endif /* GNU_EFI_X86_64_SETJMP_H */ diff --git a/gnu-efi/inc/x86_64/pe.h b/gnu-efi/inc/x86_64/pe.h new file mode 100644 index 0000000..979b936 --- /dev/null +++ b/gnu-efi/inc/x86_64/pe.h @@ -0,0 +1,595 @@ +/* + PE32+ header file + */ +#ifndef _PE_H +#define _PE_H + +#define IMAGE_DOS_SIGNATURE 0x5A4D // MZ +#define IMAGE_OS2_SIGNATURE 0x454E // NE +#define IMAGE_OS2_SIGNATURE_LE 0x454C // LE +#define IMAGE_NT_SIGNATURE 0x00004550 // PE00 +#define IMAGE_EDOS_SIGNATURE 0x44454550 // PEED + + +typedef struct _IMAGE_DOS_HEADER { // DOS .EXE header + UINT16 e_magic; // Magic number + UINT16 e_cblp; // Bytes on last page of file + UINT16 e_cp; // Pages in file + UINT16 e_crlc; // Relocations + UINT16 e_cparhdr; // Size of header in paragraphs + UINT16 e_minalloc; // Minimum extra paragraphs needed + UINT16 e_maxalloc; // Maximum extra paragraphs needed + UINT16 e_ss; // Initial (relative) SS value + UINT16 e_sp; // Initial SP value + UINT16 e_csum; // Checksum + UINT16 e_ip; // Initial IP value + UINT16 e_cs; // Initial (relative) CS value + UINT16 e_lfarlc; // File address of relocation table + UINT16 e_ovno; // Overlay number + UINT16 e_res[4]; // Reserved words + UINT16 e_oemid; // OEM identifier (for e_oeminfo) + UINT16 e_oeminfo; // OEM information; e_oemid specific + UINT16 e_res2[10]; // Reserved words + UINT32 e_lfanew; // File address of new exe header + } IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER; + +typedef struct _IMAGE_OS2_HEADER { // OS/2 .EXE header + UINT16 ne_magic; // Magic number + UINT8 ne_ver; // Version number + UINT8 ne_rev; // Revision number + UINT16 ne_enttab; // Offset of Entry Table + UINT16 ne_cbenttab; // Number of bytes in Entry Table + UINT32 ne_crc; // Checksum of whole file + UINT16 ne_flags; // Flag UINT16 + UINT16 ne_autodata; // Automatic data segment number + UINT16 ne_heap; // Initial heap allocation + UINT16 ne_stack; // Initial stack allocation + UINT32 ne_csip; // Initial CS:IP setting + UINT32 ne_sssp; // Initial SS:SP setting + UINT16 ne_cseg; // Count of file segments + UINT16 ne_cmod; // Entries in Module Reference Table + UINT16 ne_cbnrestab; // Size of non-resident name table + UINT16 ne_segtab; // Offset of Segment Table + UINT16 ne_rsrctab; // Offset of Resource Table + UINT16 ne_restab; // Offset of resident name table + UINT16 ne_modtab; // Offset of Module Reference Table + UINT16 ne_imptab; // Offset of Imported Names Table + UINT32 ne_nrestab; // Offset of Non-resident Names Table + UINT16 ne_cmovent; // Count of movable entries + UINT16 ne_align; // Segment alignment shift count + UINT16 ne_cres; // Count of resource segments + UINT8 ne_exetyp; // Target Operating system + UINT8 ne_flagsothers; // Other .EXE flags + UINT16 ne_pretthunks; // offset to return thunks + UINT16 ne_psegrefbytes; // offset to segment ref. bytes + UINT16 ne_swaparea; // Minimum code swap area size + UINT16 ne_expver; // Expected Windows version number + } IMAGE_OS2_HEADER, *PIMAGE_OS2_HEADER; + +// +// File header format. +// + +typedef struct _IMAGE_FILE_HEADER { + UINT16 Machine; + UINT16 NumberOfSections; + UINT32 TimeDateStamp; + UINT32 PointerToSymbolTable; + UINT32 NumberOfSymbols; + UINT16 SizeOfOptionalHeader; + UINT16 Characteristics; +} IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER; + +#define IMAGE_SIZEOF_FILE_HEADER 20 + +#define IMAGE_FILE_RELOCS_STRIPPED 0x0001 // Relocation info stripped from file. +#define IMAGE_FILE_EXECUTABLE_IMAGE 0x0002 // File is executable (i.e. no unresolved externel references). +#define IMAGE_FILE_LINE_NUMS_STRIPPED 0x0004 // Line nunbers stripped from file. +#define IMAGE_FILE_LOCAL_SYMS_STRIPPED 0x0008 // Local symbols stripped from file. +#define IMAGE_FILE_BYTES_REVERSED_LO 0x0080 // Bytes of machine word are reversed. +#define IMAGE_FILE_32BIT_MACHINE 0x0100 // 32 bit word machine. +#define IMAGE_FILE_DEBUG_STRIPPED 0x0200 // Debugging info stripped from file in .DBG file +#define IMAGE_FILE_SYSTEM 0x1000 // System File. +#define IMAGE_FILE_DLL 0x2000 // File is a DLL. +#define IMAGE_FILE_BYTES_REVERSED_HI 0x8000 // Bytes of machine word are reversed. + +#define IMAGE_FILE_MACHINE_UNKNOWN 0 +#define IMAGE_FILE_MACHINE_I386 0x14c // Intel 386. +#define IMAGE_FILE_MACHINE_R3000 0x162 // MIPS little-endian, 0540 big-endian +#define IMAGE_FILE_MACHINE_R4000 0x166 // MIPS little-endian +#define IMAGE_FILE_MACHINE_ALPHA 0x184 // Alpha_AXP +#define IMAGE_FILE_MACHINE_ARMTHUMB_MIXED 0x1c2 // Arm/Thumb +#define IMAGE_FILE_MACHINE_POWERPC 0x1F0 // IBM PowerPC Little-Endian +#define IMAGE_FILE_MACHINE_IA64 0x200 // IA-64 +#define IMAGE_FILE_MACHINE_TAHOE 0x7cc // Intel EM machine +#define IMAGE_FILE_MACHINE_EBC 0xebc // EFI Byte Code +#define IMAGE_FILE_MACHINE_X64 0x8664 // x86_64 +// +// Directory format. +// + +typedef struct _IMAGE_DATA_DIRECTORY { + UINT32 VirtualAddress; + UINT32 Size; +} IMAGE_DATA_DIRECTORY, *PIMAGE_DATA_DIRECTORY; + +#define IMAGE_NUMBEROF_DIRECTORY_ENTRIES 16 + +// +// Optional header format. +// + +typedef struct _IMAGE_OPTIONAL_HEADER { + // + // Standard fields. + // + + UINT16 Magic; + UINT8 MajorLinkerVersion; + UINT8 MinorLinkerVersion; + UINT32 SizeOfCode; + UINT32 SizeOfInitializedData; + UINT32 SizeOfUninitializedData; + UINT32 AddressOfEntryPoint; + UINT32 BaseOfCode; + UINT32 BaseOfData; + + // + // NT additional fields. + // + + UINT32 ImageBase; + UINT32 SectionAlignment; + UINT32 FileAlignment; + UINT16 MajorOperatingSystemVersion; + UINT16 MinorOperatingSystemVersion; + UINT16 MajorImageVersion; + UINT16 MinorImageVersion; + UINT16 MajorSubsystemVersion; + UINT16 MinorSubsystemVersion; + UINT32 Reserved1; + UINT32 SizeOfImage; + UINT32 SizeOfHeaders; + UINT32 CheckSum; + UINT16 Subsystem; + UINT16 DllCharacteristics; + UINT32 SizeOfStackReserve; + UINT32 SizeOfStackCommit; + UINT32 SizeOfHeapReserve; + UINT32 SizeOfHeapCommit; + UINT32 LoaderFlags; + UINT32 NumberOfRvaAndSizes; + IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES]; +} IMAGE_OPTIONAL_HEADER, *PIMAGE_OPTIONAL_HEADER; + +typedef struct _IMAGE_ROM_OPTIONAL_HEADER { + UINT16 Magic; + UINT8 MajorLinkerVersion; + UINT8 MinorLinkerVersion; + UINT32 SizeOfCode; + UINT32 SizeOfInitializedData; + UINT32 SizeOfUninitializedData; + UINT32 AddressOfEntryPoint; + UINT32 BaseOfCode; + UINT32 BaseOfData; + UINT32 BaseOfBss; + UINT32 GprMask; + UINT32 CprMask[4]; + UINT32 GpValue; +} IMAGE_ROM_OPTIONAL_HEADER, *PIMAGE_ROM_OPTIONAL_HEADER; + +#define IMAGE_SIZEOF_ROM_OPTIONAL_HEADER 56 +#define IMAGE_SIZEOF_STD_OPTIONAL_HEADER 28 +#define IMAGE_SIZEOF_NT_OPTIONAL_HEADER 224 + +#define IMAGE_NT_OPTIONAL_HDR_MAGIC 0x10b +#define IMAGE_ROM_OPTIONAL_HDR_MAGIC 0x107 + +typedef struct _IMAGE_NT_HEADERS { + UINT32 Signature; + IMAGE_FILE_HEADER FileHeader; + IMAGE_OPTIONAL_HEADER OptionalHeader; +} IMAGE_NT_HEADERS, *PIMAGE_NT_HEADERS; + +typedef struct _IMAGE_ROM_HEADERS { + IMAGE_FILE_HEADER FileHeader; + IMAGE_ROM_OPTIONAL_HEADER OptionalHeader; +} IMAGE_ROM_HEADERS, *PIMAGE_ROM_HEADERS; + +#define IMAGE_FIRST_SECTION( ntheader ) ((PIMAGE_SECTION_HEADER) \ + ((UINT32)ntheader + \ + FIELD_OFFSET( IMAGE_NT_HEADERS, OptionalHeader ) + \ + ((PIMAGE_NT_HEADERS)(ntheader))->FileHeader.SizeOfOptionalHeader \ + )) + + +// Subsystem Values + +#define IMAGE_SUBSYSTEM_UNKNOWN 0 // Unknown subsystem. +#define IMAGE_SUBSYSTEM_NATIVE 1 // Image doesn't require a subsystem. +#define IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem. +#define IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem. +#define IMAGE_SUBSYSTEM_OS2_CUI 5 // image runs in the OS/2 character subsystem. +#define IMAGE_SUBSYSTEM_POSIX_CUI 7 // image run in the Posix character subsystem. + + +// Directory Entries + +#define IMAGE_DIRECTORY_ENTRY_EXPORT 0 // Export Directory +#define IMAGE_DIRECTORY_ENTRY_IMPORT 1 // Import Directory +#define IMAGE_DIRECTORY_ENTRY_RESOURCE 2 // Resource Directory +#define IMAGE_DIRECTORY_ENTRY_EXCEPTION 3 // Exception Directory +#define IMAGE_DIRECTORY_ENTRY_SECURITY 4 // Security Directory +#define IMAGE_DIRECTORY_ENTRY_BASERELOC 5 // Base Relocation Table +#define IMAGE_DIRECTORY_ENTRY_DEBUG 6 // Debug Directory +#define IMAGE_DIRECTORY_ENTRY_COPYRIGHT 7 // Description String +#define IMAGE_DIRECTORY_ENTRY_GLOBALPTR 8 // Machine Value (MIPS GP) +#define IMAGE_DIRECTORY_ENTRY_TLS 9 // TLS Directory +#define IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG 10 // Load Configuration Directory + +// +// Section header format. +// + +#define IMAGE_SIZEOF_SHORT_NAME 8 + +typedef struct _IMAGE_SECTION_HEADER { + UINT8 Name[IMAGE_SIZEOF_SHORT_NAME]; + union { + UINT32 PhysicalAddress; + UINT32 VirtualSize; + } Misc; + UINT32 VirtualAddress; + UINT32 SizeOfRawData; + UINT32 PointerToRawData; + UINT32 PointerToRelocations; + UINT32 PointerToLinenumbers; + UINT16 NumberOfRelocations; + UINT16 NumberOfLinenumbers; + UINT32 Characteristics; +} IMAGE_SECTION_HEADER, *PIMAGE_SECTION_HEADER; + +#define IMAGE_SIZEOF_SECTION_HEADER 40 + +#define IMAGE_SCN_TYPE_NO_PAD 0x00000008 // Reserved. + +#define IMAGE_SCN_CNT_CODE 0x00000020 // Section contains code. +#define IMAGE_SCN_CNT_INITIALIZED_DATA 0x00000040 // Section contains initialized data. +#define IMAGE_SCN_CNT_UNINITIALIZED_DATA 0x00000080 // Section contains uninitialized data. + +#define IMAGE_SCN_LNK_OTHER 0x00000100 // Reserved. +#define IMAGE_SCN_LNK_INFO 0x00000200 // Section contains comments or some other type of information. +#define IMAGE_SCN_LNK_REMOVE 0x00000800 // Section contents will not become part of image. +#define IMAGE_SCN_LNK_COMDAT 0x00001000 // Section contents comdat. + +#define IMAGE_SCN_ALIGN_1BYTES 0x00100000 // +#define IMAGE_SCN_ALIGN_2BYTES 0x00200000 // +#define IMAGE_SCN_ALIGN_4BYTES 0x00300000 // +#define IMAGE_SCN_ALIGN_8BYTES 0x00400000 // +#define IMAGE_SCN_ALIGN_16BYTES 0x00500000 // Default alignment if no others are specified. +#define IMAGE_SCN_ALIGN_32BYTES 0x00600000 // +#define IMAGE_SCN_ALIGN_64BYTES 0x00700000 // + +#define IMAGE_SCN_MEM_DISCARDABLE 0x02000000 // Section can be discarded. +#define IMAGE_SCN_MEM_NOT_CACHED 0x04000000 // Section is not cachable. +#define IMAGE_SCN_MEM_NOT_PAGED 0x08000000 // Section is not pageable. +#define IMAGE_SCN_MEM_SHARED 0x10000000 // Section is shareable. +#define IMAGE_SCN_MEM_EXECUTE 0x20000000 // Section is executable. +#define IMAGE_SCN_MEM_READ 0x40000000 // Section is readable. +#define IMAGE_SCN_MEM_WRITE 0x80000000 // Section is writeable. + +// +// Symbol format. +// + + +#define IMAGE_SIZEOF_SYMBOL 18 + +// +// Section values. +// +// Symbols have a section number of the section in which they are +// defined. Otherwise, section numbers have the following meanings: +// + +#define IMAGE_SYM_UNDEFINED (UINT16)0 // Symbol is undefined or is common. +#define IMAGE_SYM_ABSOLUTE (UINT16)-1 // Symbol is an absolute value. +#define IMAGE_SYM_DEBUG (UINT16)-2 // Symbol is a special debug item. + +// +// Type (fundamental) values. +// + +#define IMAGE_SYM_TYPE_NULL 0 // no type. +#define IMAGE_SYM_TYPE_VOID 1 // +#define IMAGE_SYM_TYPE_CHAR 2 // type character. +#define IMAGE_SYM_TYPE_SHORT 3 // type short integer. +#define IMAGE_SYM_TYPE_INT 4 // +#define IMAGE_SYM_TYPE_LONG 5 // +#define IMAGE_SYM_TYPE_FLOAT 6 // +#define IMAGE_SYM_TYPE_DOUBLE 7 // +#define IMAGE_SYM_TYPE_STRUCT 8 // +#define IMAGE_SYM_TYPE_UNION 9 // +#define IMAGE_SYM_TYPE_ENUM 10 // enumeration. +#define IMAGE_SYM_TYPE_MOE 11 // member of enumeration. +#define IMAGE_SYM_TYPE_BYTE 12 // +#define IMAGE_SYM_TYPE_WORD 13 // +#define IMAGE_SYM_TYPE_UINT 14 // +#define IMAGE_SYM_TYPE_DWORD 15 // + +// +// Type (derived) values. +// + +#define IMAGE_SYM_DTYPE_NULL 0 // no derived type. +#define IMAGE_SYM_DTYPE_POINTER 1 // pointer. +#define IMAGE_SYM_DTYPE_FUNCTION 2 // function. +#define IMAGE_SYM_DTYPE_ARRAY 3 // array. + +// +// Storage classes. +// + +#define IMAGE_SYM_CLASS_END_OF_FUNCTION (BYTE )-1 +#define IMAGE_SYM_CLASS_NULL 0 +#define IMAGE_SYM_CLASS_AUTOMATIC 1 +#define IMAGE_SYM_CLASS_EXTERNAL 2 +#define IMAGE_SYM_CLASS_STATIC 3 +#define IMAGE_SYM_CLASS_REGISTER 4 +#define IMAGE_SYM_CLASS_EXTERNAL_DEF 5 +#define IMAGE_SYM_CLASS_LABEL 6 +#define IMAGE_SYM_CLASS_UNDEFINED_LABEL 7 +#define IMAGE_SYM_CLASS_MEMBER_OF_STRUCT 8 +#define IMAGE_SYM_CLASS_ARGUMENT 9 +#define IMAGE_SYM_CLASS_STRUCT_TAG 10 +#define IMAGE_SYM_CLASS_MEMBER_OF_UNION 11 +#define IMAGE_SYM_CLASS_UNION_TAG 12 +#define IMAGE_SYM_CLASS_TYPE_DEFINITION 13 +#define IMAGE_SYM_CLASS_UNDEFINED_STATIC 14 +#define IMAGE_SYM_CLASS_ENUM_TAG 15 +#define IMAGE_SYM_CLASS_MEMBER_OF_ENUM 16 +#define IMAGE_SYM_CLASS_REGISTER_PARAM 17 +#define IMAGE_SYM_CLASS_BIT_FIELD 18 +#define IMAGE_SYM_CLASS_BLOCK 100 +#define IMAGE_SYM_CLASS_FUNCTION 101 +#define IMAGE_SYM_CLASS_END_OF_STRUCT 102 +#define IMAGE_SYM_CLASS_FILE 103 +// new +#define IMAGE_SYM_CLASS_SECTION 104 +#define IMAGE_SYM_CLASS_WEAK_EXTERNAL 105 + +// type packing constants + +#define N_BTMASK 017 +#define N_TMASK 060 +#define N_TMASK1 0300 +#define N_TMASK2 0360 +#define N_BTSHFT 4 +#define N_TSHIFT 2 + +// MACROS + +// +// Communal selection types. +// + +#define IMAGE_COMDAT_SELECT_NODUPLICATES 1 +#define IMAGE_COMDAT_SELECT_ANY 2 +#define IMAGE_COMDAT_SELECT_SAME_SIZE 3 +#define IMAGE_COMDAT_SELECT_EXACT_MATCH 4 +#define IMAGE_COMDAT_SELECT_ASSOCIATIVE 5 + +#define IMAGE_WEAK_EXTERN_SEARCH_NOLIBRARY 1 +#define IMAGE_WEAK_EXTERN_SEARCH_LIBRARY 2 +#define IMAGE_WEAK_EXTERN_SEARCH_ALIAS 3 + + +// +// Relocation format. +// + +typedef struct _IMAGE_RELOCATION { + UINT32 VirtualAddress; + UINT32 SymbolTableIndex; + UINT16 Type; +} IMAGE_RELOCATION; + +#define IMAGE_SIZEOF_RELOCATION 10 + +// +// I386 relocation types. +// + +#define IMAGE_REL_I386_ABSOLUTE 0 // Reference is absolute, no relocation is necessary +#define IMAGE_REL_I386_DIR16 01 // Direct 16-bit reference to the symbols virtual address +#define IMAGE_REL_I386_REL16 02 // PC-relative 16-bit reference to the symbols virtual address +#define IMAGE_REL_I386_DIR32 06 // Direct 32-bit reference to the symbols virtual address +#define IMAGE_REL_I386_DIR32NB 07 // Direct 32-bit reference to the symbols virtual address, base not included +#define IMAGE_REL_I386_SEG12 011 // Direct 16-bit reference to the segment-selector bits of a 32-bit virtual address +#define IMAGE_REL_I386_SECTION 012 +#define IMAGE_REL_I386_SECREL 013 +#define IMAGE_REL_I386_REL32 024 // PC-relative 32-bit reference to the symbols virtual address + +// +// MIPS relocation types. +// + +#define IMAGE_REL_MIPS_ABSOLUTE 0 // Reference is absolute, no relocation is necessary +#define IMAGE_REL_MIPS_REFHALF 01 +#define IMAGE_REL_MIPS_REFWORD 02 +#define IMAGE_REL_MIPS_JMPADDR 03 +#define IMAGE_REL_MIPS_REFHI 04 +#define IMAGE_REL_MIPS_REFLO 05 +#define IMAGE_REL_MIPS_GPREL 06 +#define IMAGE_REL_MIPS_LITERAL 07 +#define IMAGE_REL_MIPS_SECTION 012 +#define IMAGE_REL_MIPS_SECREL 013 +#define IMAGE_REL_MIPS_REFWORDNB 042 +#define IMAGE_REL_MIPS_PAIR 045 + +// +// Alpha Relocation types. +// + +#define IMAGE_REL_ALPHA_ABSOLUTE 0x0 +#define IMAGE_REL_ALPHA_REFLONG 0x1 +#define IMAGE_REL_ALPHA_REFQUAD 0x2 +#define IMAGE_REL_ALPHA_GPREL32 0x3 +#define IMAGE_REL_ALPHA_LITERAL 0x4 +#define IMAGE_REL_ALPHA_LITUSE 0x5 +#define IMAGE_REL_ALPHA_GPDISP 0x6 +#define IMAGE_REL_ALPHA_BRADDR 0x7 +#define IMAGE_REL_ALPHA_HINT 0x8 +#define IMAGE_REL_ALPHA_INLINE_REFLONG 0x9 +#define IMAGE_REL_ALPHA_REFHI 0xA +#define IMAGE_REL_ALPHA_REFLO 0xB +#define IMAGE_REL_ALPHA_PAIR 0xC +#define IMAGE_REL_ALPHA_MATCH 0xD +#define IMAGE_REL_ALPHA_SECTION 0xE +#define IMAGE_REL_ALPHA_SECREL 0xF +#define IMAGE_REL_ALPHA_REFLONGNB 0x10 + +// +// IBM PowerPC relocation types. +// + +#define IMAGE_REL_PPC_ABSOLUTE 0x0000 // NOP +#define IMAGE_REL_PPC_ADDR64 0x0001 // 64-bit address +#define IMAGE_REL_PPC_ADDR32 0x0002 // 32-bit address +#define IMAGE_REL_PPC_ADDR24 0x0003 // 26-bit address, shifted left 2 (branch absolute) +#define IMAGE_REL_PPC_ADDR16 0x0004 // 16-bit address +#define IMAGE_REL_PPC_ADDR14 0x0005 // 16-bit address, shifted left 2 (load doubleword) +#define IMAGE_REL_PPC_REL24 0x0006 // 26-bit PC-relative offset, shifted left 2 (branch relative) +#define IMAGE_REL_PPC_REL14 0x0007 // 16-bit PC-relative offset, shifted left 2 (br cond relative) +#define IMAGE_REL_PPC_TOCREL16 0x0008 // 16-bit offset from TOC base +#define IMAGE_REL_PPC_TOCREL14 0x0009 // 16-bit offset from TOC base, shifted left 2 (load doubleword) + +#define IMAGE_REL_PPC_ADDR32NB 0x000A // 32-bit addr w/o image base +#define IMAGE_REL_PPC_SECREL 0x000B // va of containing section (as in an image sectionhdr) +#define IMAGE_REL_PPC_SECTION 0x000C // sectionheader number +#define IMAGE_REL_PPC_IFGLUE 0x000D // substitute TOC restore instruction iff symbol is glue code +#define IMAGE_REL_PPC_IMGLUE 0x000E // symbol is glue code; virtual address is TOC restore instruction + +#define IMAGE_REL_PPC_TYPEMASK 0x00FF // mask to isolate above values in IMAGE_RELOCATION.Type + +// Flag bits in IMAGE_RELOCATION.TYPE + +#define IMAGE_REL_PPC_NEG 0x0100 // subtract reloc value rather than adding it +#define IMAGE_REL_PPC_BRTAKEN 0x0200 // fix branch prediction bit to predict branch taken +#define IMAGE_REL_PPC_BRNTAKEN 0x0400 // fix branch prediction bit to predict branch not taken +#define IMAGE_REL_PPC_TOCDEFN 0x0800 // toc slot defined in file (or, data in toc) + +// +// Based relocation format. +// + +typedef struct _IMAGE_BASE_RELOCATION { + UINT32 VirtualAddress; + UINT32 SizeOfBlock; +// UINT16 TypeOffset[1]; +} IMAGE_BASE_RELOCATION, *PIMAGE_BASE_RELOCATION; + +#define IMAGE_SIZEOF_BASE_RELOCATION 8 + +// +// Based relocation types. +// + +#define IMAGE_REL_BASED_ABSOLUTE 0 +#define IMAGE_REL_BASED_HIGH 1 +#define IMAGE_REL_BASED_LOW 2 +#define IMAGE_REL_BASED_HIGHLOW 3 +#define IMAGE_REL_BASED_HIGHADJ 4 +#define IMAGE_REL_BASED_MIPS_JMPADDR 5 +#define IMAGE_REL_BASED_IA64_IMM64 9 +#define IMAGE_REL_BASED_DIR64 10 + +// +// Line number format. +// + +typedef struct _IMAGE_LINENUMBER { + union { + UINT32 SymbolTableIndex; // Symbol table index of function name if Linenumber is 0. + UINT32 VirtualAddress; // Virtual address of line number. + } Type; + UINT16 Linenumber; // Line number. +} IMAGE_LINENUMBER; + +#define IMAGE_SIZEOF_LINENUMBER 6 + +// +// Archive format. +// + +#define IMAGE_ARCHIVE_START_SIZE 8 +#define IMAGE_ARCHIVE_START "!\n" +#define IMAGE_ARCHIVE_END "`\n" +#define IMAGE_ARCHIVE_PAD "\n" +#define IMAGE_ARCHIVE_LINKER_MEMBER "/ " +#define IMAGE_ARCHIVE_LONGNAMES_MEMBER "// " + +typedef struct _IMAGE_ARCHIVE_MEMBER_HEADER { + UINT8 Name[16]; // File member name - `/' terminated. + UINT8 Date[12]; // File member date - decimal. + UINT8 UserID[6]; // File member user id - decimal. + UINT8 GroupID[6]; // File member group id - decimal. + UINT8 Mode[8]; // File member mode - octal. + UINT8 Size[10]; // File member size - decimal. + UINT8 EndHeader[2]; // String to end header. +} IMAGE_ARCHIVE_MEMBER_HEADER, *PIMAGE_ARCHIVE_MEMBER_HEADER; + +#define IMAGE_SIZEOF_ARCHIVE_MEMBER_HDR 60 + +// +// DLL support. +// + +// +// Export Format +// + +typedef struct _IMAGE_EXPORT_DIRECTORY { + UINT32 Characteristics; + UINT32 TimeDateStamp; + UINT16 MajorVersion; + UINT16 MinorVersion; + UINT32 Name; + UINT32 Base; + UINT32 NumberOfFunctions; + UINT32 NumberOfNames; + UINT32 *AddressOfFunctions; + UINT32 *AddressOfNames; + UINT32 *AddressOfNameOrdinals; +} IMAGE_EXPORT_DIRECTORY, *PIMAGE_EXPORT_DIRECTORY; + +// +// Import Format +// + +typedef struct _IMAGE_IMPORT_BY_NAME { + UINT16 Hint; + UINT8 Name[1]; +} IMAGE_IMPORT_BY_NAME, *PIMAGE_IMPORT_BY_NAME; + +typedef struct _IMAGE_THUNK_DATA { + union { + UINT32 Function; + UINT32 Ordinal; + PIMAGE_IMPORT_BY_NAME AddressOfData; + } u1; +} IMAGE_THUNK_DATA, *PIMAGE_THUNK_DATA; + +#define IMAGE_ORDINAL_FLAG 0x80000000 +#define IMAGE_SNAP_BY_ORDINAL(Ordinal) ((Ordinal & IMAGE_ORDINAL_FLAG) != 0) +#define IMAGE_ORDINAL(Ordinal) (Ordinal & 0xffff) + +typedef struct _IMAGE_IMPORT_DESCRIPTOR { + UINT32 Characteristics; + UINT32 TimeDateStamp; + UINT32 ForwarderChain; + UINT32 Name; + PIMAGE_THUNK_DATA FirstThunk; +} IMAGE_IMPORT_DESCRIPTOR, *PIMAGE_IMPORT_DESCRIPTOR; + +#endif diff --git a/gnu-efi/lib/Makefile b/gnu-efi/lib/Makefile new file mode 100644 index 0000000..0e6410d --- /dev/null +++ b/gnu-efi/lib/Makefile @@ -0,0 +1,93 @@ +# +# Copyright (C) 1999-2001 Hewlett-Packard Co. +# Contributed by David Mosberger +# Contributed by Stephane Eranian +# +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following +# disclaimer in the documentation and/or other materials +# provided with the distribution. +# * Neither the name of Hewlett-Packard Co. nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND +# CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +# INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS +# BE LIABLE FOR ANYDIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, +# OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR +# TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF +# THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. +# + +SRCDIR = . + +VPATH = $(SRCDIR) + +include $(SRCDIR)/../Make.defaults + +TOPDIR = $(SRCDIR)/.. + +CDIR = $(TOPDIR)/.. +FILES = boxdraw smbios console crc data debug dpath \ + error event exit guid hand hw init lock \ + misc print sread str cmdline \ + runtime/rtlock runtime/efirtlib runtime/rtstr runtime/vm runtime/rtdata \ + $(ARCH)/initplat $(ARCH)/math $(ARCH)/setjmp + +ifeq ($(ARCH),ia64) +FILES += $(ARCH)/salpal $(ARCH)/palproc +endif + +ifeq ($(ARCH),x86_64) +FILES += $(ARCH)/callwrap $(ARCH)/efi_stub +endif + +ifeq ($(ARCH),arm) +FILES += $(ARCH)/uldiv $(ARCH)/ldivmod $(ARCH)/div $(ARCH)/llsl $(ARCH)/llsr \ + $(ARCH)/mullu +endif + +OBJS = $(FILES:%=%.o) + +SUBDIRS = ia32 x86_64 ia64 aarch64 arm mips64el runtime + +LIBDIRINSTALL = $(INSTALLROOT)$(LIBDIR) + +all: libsubdirs libefi.a + +.PHONY: libsubdirs +libsubdirs: + for sdir in $(SUBDIRS); do mkdir -p $$sdir; done + +libefi.a: $(OBJS) + $(AR) $(ARFLAGS) $@ $^ + +clean: + rm -f libefi.a *~ $(OBJS) */*.o + +$(LIBDIRINSTALL): + mkdir -p $@ + +$(LIBDIRINSTALL)/libefi.a: libefi.a | $(LIBDIRINSTALL) + $(INSTALL) -m 644 $< $(dir $@) + +install: $(LIBDIRINSTALL)/libefi.a + +include $(SRCDIR)/../Make.rules + +.PHONY: libsubdirs diff --git a/gnu-efi/lib/Makefile.orig b/gnu-efi/lib/Makefile.orig new file mode 100644 index 0000000..65aa8ca --- /dev/null +++ b/gnu-efi/lib/Makefile.orig @@ -0,0 +1,91 @@ +# +# Copyright (C) 1999-2001 Hewlett-Packard Co. +# Contributed by David Mosberger +# Contributed by Stephane Eranian +# +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following +# disclaimer in the documentation and/or other materials +# provided with the distribution. +# * Neither the name of Hewlett-Packard Co. nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND +# CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +# INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS +# BE LIABLE FOR ANYDIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, +# OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR +# TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF +# THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. +# + +SRCDIR = . + +VPATH = $(SRCDIR) + +include $(SRCDIR)/../Make.defaults + +TOPDIR = $(SRCDIR)/.. + +CDIR = $(TOPDIR)/.. +FILES = boxdraw smbios console crc data debug dpath \ + error event guid hand hw init lock \ + misc print sread str cmdline \ + runtime/rtlock runtime/efirtlib runtime/rtstr runtime/vm runtime/rtdata \ + $(ARCH)/initplat $(ARCH)/math + +ifeq ($(ARCH),ia64) +FILES += $(ARCH)/salpal $(ARCH)/palproc +endif + +ifeq ($(ARCH),x86_64) +FILES += $(ARCH)/callwrap $(ARCH)/efi_stub +endif + +ifeq ($(ARCH),arm) +FILES += $(ARCH)/lib1funcs $(ARCH)/div64 +endif + +OBJS = $(FILES:%=%.o) + +SUBDIRS = ia32 x86_64 ia64 aarch64 arm runtime + +LIBDIRINSTALL = $(INSTALLROOT)$(LIBDIR) + +all: libsubdirs libefi.a + +.PHONY: libsubdirs +libsubdirs: + for sdir in $(SUBDIRS); do mkdir -p $$sdir; done + +libefi.a: $(patsubst %,libefi.a(%),$(OBJS)) + +clean: + rm -f libefi.a *~ $(OBJS) */*.o + +$(LIBDIRINSTALL): + mkdir -p $@ + +$(LIBDIRINSTALL)/libefi.a: libefi.a | $(LIBDIRINSTALL) + $(INSTALL) -m 644 $< $(dir $@) + +install: $(LIBDIRINSTALL)/libefi.a + +include $(SRCDIR)/../Make.rules + +.PHONY: libsubdirs diff --git a/gnu-efi/lib/aarch64/efi_stub.S b/gnu-efi/lib/aarch64/efi_stub.S new file mode 100644 index 0000000..464eae5 --- /dev/null +++ b/gnu-efi/lib/aarch64/efi_stub.S @@ -0,0 +1 @@ +/* This stub is a stub to make the build happy */ diff --git a/gnu-efi/lib/aarch64/initplat.c b/gnu-efi/lib/aarch64/initplat.c new file mode 100644 index 0000000..6c5e1fa --- /dev/null +++ b/gnu-efi/lib/aarch64/initplat.c @@ -0,0 +1,26 @@ +/* + * Copright (C) 2014 Linaro Ltd. + * Author: Ard Biesheuvel + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice and this list of conditions, without modification. + * 2. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * Alternatively, this software may be distributed 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. + */ + +#include "lib.h" + +VOID +InitializeLibPlatform ( + IN EFI_HANDLE ImageHandle EFI_UNUSED, + IN EFI_SYSTEM_TABLE *SystemTable EFI_UNUSED + ) +{ +} diff --git a/gnu-efi/lib/aarch64/math.c b/gnu-efi/lib/aarch64/math.c new file mode 100644 index 0000000..8c16444 --- /dev/null +++ b/gnu-efi/lib/aarch64/math.c @@ -0,0 +1,63 @@ +/* + * Copright (C) 2014 Linaro Ltd. + * Author: Ard Biesheuvel + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice and this list of conditions, without modification. + * 2. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * Alternatively, this software may be distributed 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. + */ + +#include "lib.h" + +UINT64 +LShiftU64 ( + IN UINT64 Operand, + IN UINTN Count + ) +// Left shift 64bit by 32bit and get a 64bit result +{ + return Operand << Count; +} + +UINT64 +RShiftU64 ( + IN UINT64 Operand, + IN UINTN Count + ) +// Right shift 64bit by 32bit and get a 64bit result +{ + return Operand >> Count; +} + + +UINT64 +MultU64x32 ( + IN UINT64 Multiplicand, + IN UINTN Multiplier + ) +// Multiple 64bit by 32bit and get a 64bit result +{ + return Multiplicand * Multiplier; +} + +UINT64 +DivU64x32 ( + IN UINT64 Dividend, + IN UINTN Divisor, + OUT UINTN *Remainder OPTIONAL + ) +// divide 64bit by 32bit and get a 64bit result +// N.B. only works for 31bit divisors!! +{ + if (Remainder) + *Remainder = Dividend % Divisor; + return Dividend / Divisor; +} diff --git a/gnu-efi/lib/aarch64/setjmp.S b/gnu-efi/lib/aarch64/setjmp.S new file mode 100644 index 0000000..46c29b1 --- /dev/null +++ b/gnu-efi/lib/aarch64/setjmp.S @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved. + * This program and the accompanying materials are licensed and made +available + * under the terms and conditions of the BSD License which accompanies +this + * distribution. The full text of the license may be found at + * http://opensource.org/licenses/bsd-license.php. + * + * THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" +BASIS, + * WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR + * IMPLIED. + */ + .text + .p2align 3 + +#define GPR_LAYOUT \ + REG_PAIR (x19, x20, 0); \ + REG_PAIR (x21, x22, 16); \ + REG_PAIR (x23, x24, 32); \ + REG_PAIR (x25, x26, 48); \ + REG_PAIR (x27, x28, 64); \ + REG_PAIR (x29, x30, 80); \ + REG_ONE (x16, 96) + +#define FPR_LAYOUT \ + REG_PAIR(d8, d9, 112); \ + REG_PAIR(d10, d11, 128); \ + REG_PAIR(d12, d13, 144); \ + REG_PAIR(d14, d15, 160); + +#define REG_PAIR(REG1, REG2, OFFS) stp REG1, REG2, [x0, OFFS] +#define REG_ONE(REG1, OFFS) str REG1, [x0, OFFS] + + .globl setjmp + .type setjmp, @function +setjmp: + mov x16, sp + GPR_LAYOUT + FPR_LAYOUT + mov w0, #0 + ret + +#undef REG_PAIR +#undef REG_ONE + +#define REG_PAIR(REG1, REG2, OFFS) ldp REG1, REG2, [x0, OFFS] +#define REG_ONE(REG1, OFFS) ldr REG1, [x0, OFFS] + + .globl longjmp + .type longjmp, @function +longjmp: + GPR_LAYOUT + FPR_LAYOUT + mov sp, x16 + cmp w1, #0 + mov w0, #1 + csel w0, w1, w0, ne + br x30 diff --git a/gnu-efi/lib/arm/div.S b/gnu-efi/lib/arm/div.S new file mode 100644 index 0000000..71158b6 --- /dev/null +++ b/gnu-efi/lib/arm/div.S @@ -0,0 +1,155 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2011, ARM. All rights reserved.
+# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +#------------------------------------------------------------------------------ + +#include "edk2asm.h" + +.text +.align 2 +GCC_ASM_EXPORT(__aeabi_uidiv) +GCC_ASM_EXPORT(__aeabi_uidivmod) +GCC_ASM_EXPORT(__aeabi_idiv) +GCC_ASM_EXPORT(__aeabi_idivmod) + +# AREA Math, CODE, READONLY + +# +#UINT32 +#EFIAPI +#__aeabi_uidivmode ( +# IN UINT32 Dividen +# IN UINT32 Divisor +# ); +# + +ASM_PFX(__aeabi_uidiv): +ASM_PFX(__aeabi_uidivmod): + rsbs r12, r1, r0, LSR #4 + mov r2, #0 + bcc ASM_PFX(__arm_div4) + rsbs r12, r1, r0, LSR #8 + bcc ASM_PFX(__arm_div8) + mov r3, #0 + b ASM_PFX(__arm_div_large) + +# +#INT32 +#EFIAPI +#__aeabi_idivmode ( +# IN INT32 Dividen +# IN INT32 Divisor +# ); +# +ASM_PFX(__aeabi_idiv): +ASM_PFX(__aeabi_idivmod): + orrs r12, r0, r1 + bmi ASM_PFX(__arm_div_negative) + rsbs r12, r1, r0, LSR #1 + mov r2, #0 + bcc ASM_PFX(__arm_div1) + rsbs r12, r1, r0, LSR #4 + bcc ASM_PFX(__arm_div4) + rsbs r12, r1, r0, LSR #8 + bcc ASM_PFX(__arm_div8) + mov r3, #0 + b ASM_PFX(__arm_div_large) +ASM_PFX(__arm_div8): + rsbs r12, r1, r0, LSR #7 + subcs r0, r0, r1, LSL #7 + adc r2, r2, r2 + rsbs r12, r1, r0,LSR #6 + subcs r0, r0, r1, LSL #6 + adc r2, r2, r2 + rsbs r12, r1, r0, LSR #5 + subcs r0, r0, r1, LSL #5 + adc r2, r2, r2 + rsbs r12, r1, r0, LSR #4 + subcs r0, r0, r1, LSL #4 + adc r2, r2, r2 +ASM_PFX(__arm_div4): + rsbs r12, r1, r0, LSR #3 + subcs r0, r0, r1, LSL #3 + adc r2, r2, r2 + rsbs r12, r1, r0, LSR #2 + subcs r0, r0, r1, LSL #2 + adcs r2, r2, r2 + rsbs r12, r1, r0, LSR #1 + subcs r0, r0, r1, LSL #1 + adc r2, r2, r2 +ASM_PFX(__arm_div1): + subs r1, r0, r1 + movcc r1, r0 + adc r0, r2, r2 + bx r14 +ASM_PFX(__arm_div_negative): + ands r2, r1, #0x80000000 + rsbmi r1, r1, #0 + eors r3, r2, r0, ASR #32 + rsbcs r0, r0, #0 + rsbs r12, r1, r0, LSR #4 + bcc label1 + rsbs r12, r1, r0, LSR #8 + bcc label2 +ASM_PFX(__arm_div_large): + lsl r1, r1, #6 + rsbs r12, r1, r0, LSR #8 + orr r2, r2, #0xfc000000 + bcc label2 + lsl r1, r1, #6 + rsbs r12, r1, r0, LSR #8 + orr r2, r2, #0x3f00000 + bcc label2 + lsl r1, r1, #6 + rsbs r12, r1, r0, LSR #8 + orr r2, r2, #0xfc000 + orrcs r2, r2, #0x3f00 + lslcs r1, r1, #6 + rsbs r12, r1, #0 + bcs ASM_PFX(__aeabi_idiv0) +label3: + lsrcs r1, r1, #6 +label2: + rsbs r12, r1, r0, LSR #7 + subcs r0, r0, r1, LSL #7 + adc r2, r2, r2 + rsbs r12, r1, r0, LSR #6 + subcs r0, r0, r1, LSL #6 + adc r2, r2, r2 + rsbs r12, r1, r0, LSR #5 + subcs r0, r0, r1, LSL #5 + adc r2, r2, r2 + rsbs r12, r1, r0, LSR #4 + subcs r0, r0, r1, LSL #4 + adc r2, r2, r2 +label1: + rsbs r12, r1, r0, LSR #3 + subcs r0, r0, r1, LSL #3 + adc r2, r2, r2 + rsbs r12, r1, r0, LSR #2 + subcs r0, r0, r1, LSL #2 + adcs r2, r2, r2 + bcs label3 + rsbs r12, r1, r0, LSR #1 + subcs r0, r0, r1, LSL #1 + adc r2, r2, r2 + subs r1, r0, r1 + movcc r1, r0 + adc r0, r2, r2 + asrs r3, r3, #31 + rsbmi r0, r0, #0 + rsbcs r1, r1, #0 + bx r14 + + @ What to do about division by zero? For now, just return. +ASM_PFX(__aeabi_idiv0): + bx r14 diff --git a/gnu-efi/lib/arm/edk2asm.h b/gnu-efi/lib/arm/edk2asm.h new file mode 100644 index 0000000..9515eaf --- /dev/null +++ b/gnu-efi/lib/arm/edk2asm.h @@ -0,0 +1,6 @@ + +#define ASM_PFX(x) x +#define GCC_ASM_EXPORT(x) \ + .globl x ; \ + .type x, %function + diff --git a/gnu-efi/lib/arm/efi_stub.S b/gnu-efi/lib/arm/efi_stub.S new file mode 100644 index 0000000..464eae5 --- /dev/null +++ b/gnu-efi/lib/arm/efi_stub.S @@ -0,0 +1 @@ +/* This stub is a stub to make the build happy */ diff --git a/gnu-efi/lib/arm/initplat.c b/gnu-efi/lib/arm/initplat.c new file mode 100644 index 0000000..135a649 --- /dev/null +++ b/gnu-efi/lib/arm/initplat.c @@ -0,0 +1,34 @@ +/* + * Copright (C) 2014 Linaro Ltd. + * Author: Ard Biesheuvel + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice and this list of conditions, without modification. + * 2. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * Alternatively, this software may be distributed 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. + */ + +#include "lib.h" + +VOID +InitializeLibPlatform ( + IN EFI_HANDLE ImageHandle EFI_UNUSED, + IN EFI_SYSTEM_TABLE *SystemTable EFI_UNUSED + ) +{ +} + +#ifdef __GNUC__ +void __div0(void) +{ + // TODO handle divide by zero fault + while (1); +} +#endif diff --git a/gnu-efi/lib/arm/ldivmod.S b/gnu-efi/lib/arm/ldivmod.S new file mode 100644 index 0000000..edbf89e --- /dev/null +++ b/gnu-efi/lib/arm/ldivmod.S @@ -0,0 +1,61 @@ +//------------------------------------------------------------------------------ +// +// Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.
+// +// This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php +// +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +//------------------------------------------------------------------------------ + + +#include "edk2asm.h" + + .text + .align 2 + GCC_ASM_EXPORT(__aeabi_ldivmod) + +// +// A pair of (unsigned) long longs is returned in {{r0, r1}, {r2, r3}}, +// the quotient in {r0, r1}, and the remainder in {r2, r3}. +// +//__value_in_regs lldiv_t +//EFIAPI +//__aeabi_ldivmod ( +// IN UINT64 Dividen +// IN UINT64 Divisor +// )// +// + +ASM_PFX(__aeabi_ldivmod): + push {r4,lr} + asrs r4,r1,#1 + eor r4,r4,r3,LSR #1 + bpl L_Test1 + rsbs r0,r0,#0 + rsc r1,r1,#0 +L_Test1: + tst r3,r3 + bpl L_Test2 + rsbs r2,r2,#0 + rsc r3,r3,#0 +L_Test2: + bl ASM_PFX(__aeabi_uldivmod) + tst r4,#0x40000000 + beq L_Test3 + rsbs r0,r0,#0 + rsc r1,r1,#0 +L_Test3: + tst r4,#0x80000000 + beq L_Exit + rsbs r2,r2,#0 + rsc r3,r3,#0 +L_Exit: + pop {r4,pc} + + + diff --git a/gnu-efi/lib/arm/llsl.S b/gnu-efi/lib/arm/llsl.S new file mode 100644 index 0000000..0f5c407 --- /dev/null +++ b/gnu-efi/lib/arm/llsl.S @@ -0,0 +1,41 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2013, ARM. All rights reserved.
+# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +#------------------------------------------------------------------------------ + +#include "edk2asm.h" + +.text +.align 2 +GCC_ASM_EXPORT(__aeabi_llsl) + +# +#VOID +#EFIAPI +#__aeabi_llsl ( +# IN VOID *Destination, +# IN VOID *Source, +# IN UINT32 Size +# ); +# +ASM_PFX(__aeabi_llsl): + subs r3,r2,#0x20 + bpl 1f + rsb r3,r2,#0x20 + lsl r1,r1,r2 + orr r1,r1,r0,lsr r3 + lsl r0,r0,r2 + bx lr +1: + lsl r1,r0,r3 + mov r0,#0 + bx lr diff --git a/gnu-efi/lib/arm/llsr.S b/gnu-efi/lib/arm/llsr.S new file mode 100644 index 0000000..432b27d --- /dev/null +++ b/gnu-efi/lib/arm/llsr.S @@ -0,0 +1,41 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2013, ARM. All rights reserved.
+# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +#------------------------------------------------------------------------------ + +#include "edk2asm.h" + +.text +.align 2 +GCC_ASM_EXPORT(__aeabi_llsr) + +# +#VOID +#EFIAPI +#__aeabi_llsr ( +# IN VOID *Destination, +# IN VOID *Source, +# IN UINT32 Size +# ); +# +ASM_PFX(__aeabi_llsr): + subs r3,r2,#0x20 + bpl 1f + rsb r3,r2,#0x20 + lsr r0,r0,r2 + orr r0,r0,r1,lsl r3 + lsr r1,r1,r2 + bx lr +1: + lsr r0,r1,r3 + mov r1,#0 + bx lr diff --git a/gnu-efi/lib/arm/math.c b/gnu-efi/lib/arm/math.c new file mode 100644 index 0000000..4793ae2 --- /dev/null +++ b/gnu-efi/lib/arm/math.c @@ -0,0 +1,67 @@ +/* + * Copright (C) 2014 Linaro Ltd. + * Author: Ard Biesheuvel + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice and this list of conditions, without modification. + * 2. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * Alternatively, this software may be distributed 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. + */ + +#include "lib.h" + +UINT64 +LShiftU64 ( + IN UINT64 Operand, + IN UINTN Count + ) +// Left shift 64bit by 32bit and get a 64bit result +{ + return Operand << Count; +} + +UINT64 +RShiftU64 ( + IN UINT64 Operand, + IN UINTN Count + ) +// Right shift 64bit by 32bit and get a 64bit result +{ + return Operand >> Count; +} + + +UINT64 +MultU64x32 ( + IN UINT64 Multiplicand, + IN UINTN Multiplier + ) +// Multiply 64bit by 32bit and get a 64bit result +{ + return Multiplicand * Multiplier; +} + +UINT64 +DivU64x32 ( + IN UINT64 Dividend, + IN UINTN Divisor, + OUT UINTN *Remainder OPTIONAL + ) +{ + /* + * GCC turns a division into a multiplication and shift with precalculated + * constants if the divisor is constant and the dividend fits into a 32 bit + * variable. Otherwise, it will turn this into calls into the 32-bit div + * library functions. + */ + if (Remainder) + *Remainder = Dividend % Divisor; + return Dividend / Divisor; +} diff --git a/gnu-efi/lib/arm/mullu.S b/gnu-efi/lib/arm/mullu.S new file mode 100644 index 0000000..39b9a80 --- /dev/null +++ b/gnu-efi/lib/arm/mullu.S @@ -0,0 +1,33 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.
+# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +#------------------------------------------------------------------------------ + +#include "edk2asm.h" + +.text +GCC_ASM_EXPORT(__aeabi_lmul) +# +#INT64 +#EFIAPI +#__aeabi_lmul ( +# IN INT64 Multiplicand +# IN INT64 Multiplier +# ); +# +ASM_PFX(__aeabi_lmul): + stmdb sp!, {lr} + mov lr, r0 + umull r0, ip, r2, lr + mla r1, r2, r1, ip + mla r1, r3, lr, r1 + ldmia sp!, {pc} diff --git a/gnu-efi/lib/arm/setjmp.S b/gnu-efi/lib/arm/setjmp.S new file mode 100644 index 0000000..bd61a8d --- /dev/null +++ b/gnu-efi/lib/arm/setjmp.S @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved. + * This program and the accompanying materials are licensed and made + * available under the terms and conditions of the BSD License which + * accompanies this distribution. The full text of the license may + * be found at http://opensource.org/licenses/bsd-license.php. + * + * THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" + * BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER + * EXPRESS OR IMPLIED. + */ + .text + .arm + .globl setjmp + .type setjmp, %function +setjmp: + mov r3, r13 + stmia r0, {r3-r12,r14} + eor r0, r0, r0 + bx lr + + .globl longjmp + .type longjmp, %function +longjmp: + ldmia r0, {r3-r12,r14} diff --git a/gnu-efi/lib/arm/uldiv.S b/gnu-efi/lib/arm/uldiv.S new file mode 100644 index 0000000..f478898 --- /dev/null +++ b/gnu-efi/lib/arm/uldiv.S @@ -0,0 +1,267 @@ +//------------------------------------------------------------------------------ +// +// Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.
+// +// This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php +// +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +//------------------------------------------------------------------------------ + +#include "edk2asm.h" + + .text + .align 2 + GCC_ASM_EXPORT(__aeabi_uldivmod) + +// +//UINT64 +//EFIAPI +//__aeabi_uldivmod ( +// IN UINT64 Dividend +// IN UINT64 Divisor +// ) +// +ASM_PFX(__aeabi_uldivmod): + stmdb sp!, {r4, r5, r6, lr} + mov r4, r1 + mov r5, r0 + mov r6, #0 // 0x0 + orrs ip, r3, r2, lsr #31 + bne ASM_PFX(__aeabi_uldivmod_label1) + tst r2, r2 + beq ASM_PFX(_ll_div0) + movs ip, r2, lsr #15 + addeq r6, r6, #16 // 0x10 + mov ip, r2, lsl r6 + movs lr, ip, lsr #23 + moveq ip, ip, lsl #8 + addeq r6, r6, #8 // 0x8 + movs lr, ip, lsr #27 + moveq ip, ip, lsl #4 + addeq r6, r6, #4 // 0x4 + movs lr, ip, lsr #29 + moveq ip, ip, lsl #2 + addeq r6, r6, #2 // 0x2 + movs lr, ip, lsr #30 + moveq ip, ip, lsl #1 + addeq r6, r6, #1 // 0x1 + b ASM_PFX(_ll_udiv_small) +ASM_PFX(__aeabi_uldivmod_label1): + tst r3, #-2147483648 // 0x80000000 + bne ASM_PFX(__aeabi_uldivmod_label2) + movs ip, r3, lsr #15 + addeq r6, r6, #16 // 0x10 + mov ip, r3, lsl r6 + movs lr, ip, lsr #23 + moveq ip, ip, lsl #8 + addeq r6, r6, #8 // 0x8 + movs lr, ip, lsr #27 + moveq ip, ip, lsl #4 + addeq r6, r6, #4 // 0x4 + movs lr, ip, lsr #29 + moveq ip, ip, lsl #2 + addeq r6, r6, #2 // 0x2 + movs lr, ip, lsr #30 + addeq r6, r6, #1 // 0x1 + rsb r3, r6, #32 // 0x20 + moveq ip, ip, lsl #1 + orr ip, ip, r2, lsr r3 + mov lr, r2, lsl r6 + b ASM_PFX(_ll_udiv_big) +ASM_PFX(__aeabi_uldivmod_label2): + mov ip, r3 + mov lr, r2 + b ASM_PFX(_ll_udiv_ginormous) + +ASM_PFX(_ll_udiv_small): + cmp r4, ip, lsl #1 + mov r3, #0 // 0x0 + subcs r4, r4, ip, lsl #1 + addcs r3, r3, #2 // 0x2 + cmp r4, ip + subcs r4, r4, ip + adcs r3, r3, #0 // 0x0 + add r2, r6, #32 // 0x20 + cmp r2, #32 // 0x20 + rsb ip, ip, #0 // 0x0 + bcc ASM_PFX(_ll_udiv_small_label1) + orrs r0, r4, r5, lsr #30 + moveq r4, r5 + moveq r5, #0 // 0x0 + subeq r2, r2, #32 // 0x20 +ASM_PFX(_ll_udiv_small_label1): + mov r1, #0 // 0x0 + cmp r2, #16 // 0x10 + bcc ASM_PFX(_ll_udiv_small_label2) + movs r0, r4, lsr #14 + moveq r4, r4, lsl #16 + addeq r1, r1, #16 // 0x10 +ASM_PFX(_ll_udiv_small_label2): + sub lr, r2, r1 + cmp lr, #8 // 0x8 + bcc ASM_PFX(_ll_udiv_small_label3) + movs r0, r4, lsr #22 + moveq r4, r4, lsl #8 + addeq r1, r1, #8 // 0x8 +ASM_PFX(_ll_udiv_small_label3): + rsb r0, r1, #32 // 0x20 + sub r2, r2, r1 + orr r4, r4, r5, lsr r0 + mov r5, r5, lsl r1 + cmp r2, #1 // 0x1 + bcc ASM_PFX(_ll_udiv_small_label5) + sub r2, r2, #1 // 0x1 + and r0, r2, #7 // 0x7 + eor r0, r0, #7 // 0x7 + adds r0, r0, r0, lsl #1 + add pc, pc, r0, lsl #2 + nop // (mov r0,r0) +ASM_PFX(_ll_udiv_small_label4): + adcs r5, r5, r5 + adcs r4, ip, r4, lsl #1 + rsbcc r4, ip, r4 + adcs r5, r5, r5 + adcs r4, ip, r4, lsl #1 + rsbcc r4, ip, r4 + adcs r5, r5, r5 + adcs r4, ip, r4, lsl #1 + rsbcc r4, ip, r4 + adcs r5, r5, r5 + adcs r4, ip, r4, lsl #1 + rsbcc r4, ip, r4 + adcs r5, r5, r5 + adcs r4, ip, r4, lsl #1 + rsbcc r4, ip, r4 + adcs r5, r5, r5 + adcs r4, ip, r4, lsl #1 + rsbcc r4, ip, r4 + adcs r5, r5, r5 + adcs r4, ip, r4, lsl #1 + rsbcc r4, ip, r4 + adcs r5, r5, r5 + adcs r4, ip, r4, lsl #1 + sub r2, r2, #8 // 0x8 + tst r2, r2 + rsbcc r4, ip, r4 + bpl ASM_PFX(_ll_udiv_small_label4) +ASM_PFX(_ll_udiv_small_label5): + mov r2, r4, lsr r6 + bic r4, r4, r2, lsl r6 + adcs r0, r5, r5 + adc r1, r4, r4 + add r1, r1, r3, lsl r6 + mov r3, #0 // 0x0 + ldmia sp!, {r4, r5, r6, pc} + +ASM_PFX(_ll_udiv_big): + subs r0, r5, lr + mov r3, #0 // 0x0 + sbcs r1, r4, ip + movcs r5, r0 + movcs r4, r1 + adcs r3, r3, #0 // 0x0 + subs r0, r5, lr + sbcs r1, r4, ip + movcs r5, r0 + movcs r4, r1 + adcs r3, r3, #0 // 0x0 + subs r0, r5, lr + sbcs r1, r4, ip + movcs r5, r0 + movcs r4, r1 + adcs r3, r3, #0 // 0x0 + mov r1, #0 // 0x0 + rsbs lr, lr, #0 // 0x0 + rsc ip, ip, #0 // 0x0 + cmp r6, #16 // 0x10 + bcc ASM_PFX(_ll_udiv_big_label1) + movs r0, r4, lsr #14 + moveq r4, r4, lsl #16 + addeq r1, r1, #16 // 0x10 +ASM_PFX(_ll_udiv_big_label1): + sub r2, r6, r1 + cmp r2, #8 // 0x8 + bcc ASM_PFX(_ll_udiv_big_label2) + movs r0, r4, lsr #22 + moveq r4, r4, lsl #8 + addeq r1, r1, #8 // 0x8 +ASM_PFX(_ll_udiv_big_label2): + rsb r0, r1, #32 // 0x20 + sub r2, r6, r1 + orr r4, r4, r5, lsr r0 + mov r5, r5, lsl r1 + cmp r2, #1 // 0x1 + bcc ASM_PFX(_ll_udiv_big_label4) + sub r2, r2, #1 // 0x1 + and r0, r2, #3 // 0x3 + rsb r0, r0, #3 // 0x3 + adds r0, r0, r0, lsl #1 + add pc, pc, r0, lsl #3 + nop // (mov r0,r0) +ASM_PFX(_ll_udiv_big_label3): + adcs r5, r5, r5 + adcs r4, r4, r4 + adcs r0, lr, r5 + adcs r1, ip, r4 + movcs r5, r0 + movcs r4, r1 + adcs r5, r5, r5 + adcs r4, r4, r4 + adcs r0, lr, r5 + adcs r1, ip, r4 + movcs r5, r0 + movcs r4, r1 + adcs r5, r5, r5 + adcs r4, r4, r4 + adcs r0, lr, r5 + adcs r1, ip, r4 + movcs r5, r0 + movcs r4, r1 + sub r2, r2, #4 // 0x4 + adcs r5, r5, r5 + adcs r4, r4, r4 + adcs r0, lr, r5 + adcs r1, ip, r4 + tst r2, r2 + movcs r5, r0 + movcs r4, r1 + bpl ASM_PFX(_ll_udiv_big_label3) +ASM_PFX(_ll_udiv_big_label4): + mov r1, #0 // 0x0 + mov r2, r5, lsr r6 + bic r5, r5, r2, lsl r6 + adcs r0, r5, r5 + adc r1, r1, #0 // 0x0 + movs lr, r3, lsl r6 + mov r3, r4, lsr r6 + bic r4, r4, r3, lsl r6 + adc r1, r1, #0 // 0x0 + adds r0, r0, lr + orr r2, r2, r4, ror r6 + adc r1, r1, #0 // 0x0 + ldmia sp!, {r4, r5, r6, pc} + +ASM_PFX(_ll_udiv_ginormous): + subs r2, r5, lr + mov r1, #0 // 0x0 + sbcs r3, r4, ip + adc r0, r1, r1 + movcc r2, r5 + movcc r3, r4 + ldmia sp!, {r4, r5, r6, pc} + +ASM_PFX(_ll_div0): + ldmia sp!, {r4, r5, r6, lr} + mov r0, #0 // 0x0 + mov r1, #0 // 0x0 + b ASM_PFX(__aeabi_ldiv0) + +ASM_PFX(__aeabi_ldiv0): + bx r14 + + diff --git a/gnu-efi/lib/boxdraw.c b/gnu-efi/lib/boxdraw.c new file mode 100644 index 0000000..5865fb9 --- /dev/null +++ b/gnu-efi/lib/boxdraw.c @@ -0,0 +1,173 @@ +/*++ + +Copyright (c) 1998 Intel Corporation + +Module Name: + + BoxDraw.c + +Abstract: + Lib functions to support Box Draw Unicode code pages. + + + +Revision History + +--*/ + +#include "lib.h" + +typedef struct { + CHAR16 Unicode; + CHAR8 PcAnsi; + CHAR8 Ascii; +} UNICODE_TO_CHAR; + + +// +// This list is used to define the valid extend chars. +// It also provides a mapping from Unicode to PCANSI or +// ASCII. The ASCII mapping we just made up. +// +// + +STATIC UNICODE_TO_CHAR UnicodeToPcAnsiOrAscii[] = { + { BOXDRAW_HORIZONTAL, 0xc4, L'-'}, + { BOXDRAW_VERTICAL, 0xb3, L'|'}, + { BOXDRAW_DOWN_RIGHT, 0xda, L'/'}, + { BOXDRAW_DOWN_LEFT, 0xbf, L'\\'}, + { BOXDRAW_UP_RIGHT, 0xc0, L'\\'}, + { BOXDRAW_UP_LEFT, 0xd9, L'/'}, + { BOXDRAW_VERTICAL_RIGHT, 0xc3, L'|'}, + { BOXDRAW_VERTICAL_LEFT, 0xb4, L'|'}, + { BOXDRAW_DOWN_HORIZONTAL, 0xc2, L'+'}, + { BOXDRAW_UP_HORIZONTAL, 0xc1, L'+'}, + { BOXDRAW_VERTICAL_HORIZONTAL, 0xc5, L'+'}, + { BOXDRAW_DOUBLE_HORIZONTAL, 0xcd, L'-'}, + { BOXDRAW_DOUBLE_VERTICAL, 0xba, L'|'}, + { BOXDRAW_DOWN_RIGHT_DOUBLE, 0xd5, L'/'}, + { BOXDRAW_DOWN_DOUBLE_RIGHT, 0xd6, L'/'}, + { BOXDRAW_DOUBLE_DOWN_RIGHT, 0xc9, L'/'}, + { BOXDRAW_DOWN_LEFT_DOUBLE, 0xb8, L'\\'}, + { BOXDRAW_DOWN_DOUBLE_LEFT, 0xb7, L'\\'}, + { BOXDRAW_DOUBLE_DOWN_LEFT, 0xbb, L'\\'}, + { BOXDRAW_UP_RIGHT_DOUBLE, 0xd4, L'\\'}, + { BOXDRAW_UP_DOUBLE_RIGHT, 0xd3, L'\\'}, + { BOXDRAW_DOUBLE_UP_RIGHT, 0xc8, L'\\'}, + { BOXDRAW_UP_LEFT_DOUBLE, 0xbe, L'/'}, + { BOXDRAW_UP_DOUBLE_LEFT, 0xbd, L'/'}, + { BOXDRAW_DOUBLE_UP_LEFT, 0xbc, L'/'}, + { BOXDRAW_VERTICAL_RIGHT_DOUBLE, 0xc6, L'|'}, + { BOXDRAW_VERTICAL_DOUBLE_RIGHT, 0xc7, L'|'}, + { BOXDRAW_DOUBLE_VERTICAL_RIGHT, 0xcc, L'|'}, + { BOXDRAW_VERTICAL_LEFT_DOUBLE, 0xb5, L'|'}, + { BOXDRAW_VERTICAL_DOUBLE_LEFT, 0xb6, L'|'}, + { BOXDRAW_DOUBLE_VERTICAL_LEFT, 0xb9, L'|'}, + { BOXDRAW_DOWN_HORIZONTAL_DOUBLE, 0xd1, L'+'}, + { BOXDRAW_DOWN_DOUBLE_HORIZONTAL, 0xd2, L'+'}, + { BOXDRAW_DOUBLE_DOWN_HORIZONTAL, 0xcb, L'+'}, + { BOXDRAW_UP_HORIZONTAL_DOUBLE, 0xcf, L'+'}, + { BOXDRAW_UP_DOUBLE_HORIZONTAL, 0xd0, L'+'}, + { BOXDRAW_DOUBLE_UP_HORIZONTAL, 0xca, L'+'}, + { BOXDRAW_VERTICAL_HORIZONTAL_DOUBLE, 0xd8, L'+'}, + { BOXDRAW_VERTICAL_DOUBLE_HORIZONTAL, 0xd7, L'+'}, + { BOXDRAW_DOUBLE_VERTICAL_HORIZONTAL, 0xce, L'+'}, + + { BLOCKELEMENT_FULL_BLOCK, 0xdb, L'*'}, + { BLOCKELEMENT_LIGHT_SHADE, 0xb0, L'+'}, + + { GEOMETRICSHAPE_UP_TRIANGLE, 0x1e, L'^'}, + { GEOMETRICSHAPE_RIGHT_TRIANGLE, 0x10, L'>'}, + { GEOMETRICSHAPE_DOWN_TRIANGLE, 0x1f, L'v'}, + { GEOMETRICSHAPE_LEFT_TRIANGLE, 0x11, L'<'}, + + /* BugBug: Left Arrow is an ESC. We can not make it print + on a PCANSI terminal. If we can make left arrow + come out on PC ANSI we can add it back. + + { ARROW_LEFT, 0x1b, L'<'}, + */ + + { ARROW_UP, 0x18, L'^'}, + + /* BugBut: Took out left arrow so right has to go too. + { ARROW_RIGHT, 0x1a, L'>'}, + */ + { ARROW_DOWN, 0x19, L'v'}, + + { 0x0000, 0x00, L'\0' } +}; + + +BOOLEAN +LibIsValidTextGraphics ( + IN CHAR16 Graphic, + OUT CHAR8 *PcAnsi, OPTIONAL + OUT CHAR8 *Ascii OPTIONAL + ) +/*++ + +Routine Description: + + Detects if a Unicode char is for Box Drawing text graphics. + +Arguments: + + Grphic - Unicode char to test. + + PcAnsi - Optional pointer to return PCANSI equivalent of Graphic. + + Asci - Optional pointer to return Ascii equivalent of Graphic. + +Returns: + + TRUE if Gpaphic is a supported Unicode Box Drawing character. + +--*/{ + UNICODE_TO_CHAR *Table; + + if ((((Graphic & 0xff00) != 0x2500) && ((Graphic & 0xff00) != 0x2100))) { + + // + // Unicode drawing code charts are all in the 0x25xx range, + // arrows are 0x21xx + // + return FALSE; + } + + for (Table = UnicodeToPcAnsiOrAscii; Table->Unicode != 0x0000; Table++) { + if (Graphic == Table->Unicode) { + if (PcAnsi) { + *PcAnsi = Table->PcAnsi; + } + if (Ascii) { + *Ascii = Table->Ascii; + } + return TRUE; + } + } + return FALSE; +} + +BOOLEAN +IsValidAscii ( + IN CHAR16 Ascii + ) +{ + if ((Ascii >= 0x20) && (Ascii <= 0x7f)) { + return TRUE; + } + return FALSE; +} + +BOOLEAN +IsValidEfiCntlChar ( + IN CHAR16 c + ) +{ + if (c == CHAR_NULL || c == CHAR_BACKSPACE || c == CHAR_LINEFEED || c == CHAR_CARRIAGE_RETURN) { + return TRUE; + } + return FALSE; +} + diff --git a/gnu-efi/lib/cmdline.c b/gnu-efi/lib/cmdline.c new file mode 100644 index 0000000..f21c44c --- /dev/null +++ b/gnu-efi/lib/cmdline.c @@ -0,0 +1,121 @@ +#include "lib.h" + +#include "efiprot.h" +#include "efishellintf.h" +#include "efishellparm.h" + +#ifndef MAX_ARGV_CONTENTS_SIZE +# define MAX_CMDLINE_SIZE 1024 +#endif +#ifndef MAX_ARGC +# define MAX_CMDLINE_ARGC 32 +#endif + +/* + Parse LoadedImage options area, called only in case the regular + shell protos are not available. + + Format of LoadedImage->LoadOptions appears to be a + single-space-separated list of args (looks like the shell already + pre-parses the input, it apparently folds several consecutive spaces + into one): + argv[0] space argv[1] (etc.) argv[N] space \0 cwd \0 other data + For safety, we support the trailing \0 without a space before, as + well as several consecutive spaces (-> several args). +*/ +static +INTN +GetShellArgcArgvFromLoadedImage( + EFI_HANDLE ImageHandle, + CHAR16 **ResultArgv[] + ) +{ + EFI_STATUS Status; + void *LoadedImage = NULL; + static CHAR16 ArgvContents[MAX_CMDLINE_SIZE]; + static CHAR16 *Argv[MAX_CMDLINE_ARGC], *ArgStart, *c; + UINTN Argc = 0, BufLen; + + Status = uefi_call_wrapper(BS->OpenProtocol, 6, + ImageHandle, + &LoadedImageProtocol, + &LoadedImage, + ImageHandle, + NULL, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (EFI_ERROR(Status)) + return -1; + + BufLen = ((EFI_LOADED_IMAGE *)LoadedImage)->LoadOptionsSize; + if (BufLen < 2) /* We are expecting at least a \0 */ + return -1; + else if (BufLen > sizeof(ArgvContents)) + BufLen = sizeof(ArgvContents); + + CopyMem(ArgvContents, ((EFI_LOADED_IMAGE *)LoadedImage)->LoadOptions, BufLen); + ArgvContents[MAX_CMDLINE_SIZE - 1] = L'\0'; + + for (c = ArgStart = ArgvContents ; *c != L'\0' ; ++c) { + if (*c == L' ') { + *c = L'\0'; + if (Argc < MAX_CMDLINE_ARGC) Argv[Argc++] = ArgStart; + ArgStart = c + 1; + } + } + + if ((*ArgStart != L'\0') && (Argc < MAX_CMDLINE_ARGC)) + Argv[Argc++] = ArgStart; + + // Print(L"Got argc/argv from loaded image proto\n"); + *ResultArgv = Argv; + return Argc; +} + +INTN GetShellArgcArgv(EFI_HANDLE ImageHandle, CHAR16 **Argv[]) +{ + // Code inspired from EDK2's + // ShellPkg/Library/UefiShellCEntryLib/UefiShellCEntryLib.c (BSD) + EFI_STATUS Status; + static const EFI_GUID EfiShellParametersProtocolGuid + = EFI_SHELL_PARAMETERS_PROTOCOL_GUID; + static const EFI_GUID ShellInterfaceProtocolGuid + = SHELL_INTERFACE_PROTOCOL_GUID; + EFI_SHELL_PARAMETERS_PROTOCOL *EfiShellParametersProtocol = NULL; + EFI_SHELL_INTERFACE *EfiShellInterfaceProtocol = NULL; + + Status = uefi_call_wrapper(BS->OpenProtocol, 6, + ImageHandle, + (EFI_GUID*)&EfiShellParametersProtocolGuid, + (VOID **)&EfiShellParametersProtocol, + ImageHandle, + NULL, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (!EFI_ERROR(Status)) + { + // use shell 2.0 interface + // Print(L"Got argc/argv from shell intf proto\n"); + *Argv = EfiShellParametersProtocol->Argv; + return EfiShellParametersProtocol->Argc; + } + + // try to get shell 1.0 interface instead. + Status = uefi_call_wrapper(BS->OpenProtocol, 6, + ImageHandle, + (EFI_GUID*)&ShellInterfaceProtocolGuid, + (VOID **)&EfiShellInterfaceProtocol, + ImageHandle, + NULL, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (!EFI_ERROR(Status)) + { + // Print(L"Got argc/argv from shell params proto\n"); + *Argv = EfiShellInterfaceProtocol->Argv; + return EfiShellInterfaceProtocol->Argc; + } + + // shell 1.0 and 2.0 interfaces failed + return GetShellArgcArgvFromLoadedImage(ImageHandle, Argv); +} diff --git a/gnu-efi/lib/console.c b/gnu-efi/lib/console.c new file mode 100644 index 0000000..5ca47ef --- /dev/null +++ b/gnu-efi/lib/console.c @@ -0,0 +1,104 @@ +/*++ + +Copyright (c) 1998 Intel Corporation + +Module Name: + + console.c + +Abstract: + + + + +Revision History + +--*/ + +#include "lib.h" + + + +VOID +Output ( + IN CHAR16 *Str + ) +// Write a string to the console at the current cursor location +{ + uefi_call_wrapper(ST->ConOut->OutputString, 2, ST->ConOut, Str); +} + + +VOID +Input ( + IN CHAR16 *Prompt OPTIONAL, + OUT CHAR16 *InStr, + IN UINTN StrLen + ) +// Input a string at the current cursor location, for StrLen +{ + IInput ( + ST->ConOut, + ST->ConIn, + Prompt, + InStr, + StrLen + ); +} + +VOID +IInput ( + IN SIMPLE_TEXT_OUTPUT_INTERFACE *ConOut, + IN SIMPLE_INPUT_INTERFACE *ConIn, + IN CHAR16 *Prompt OPTIONAL, + OUT CHAR16 *InStr, + IN UINTN StrLen + ) +// Input a string at the current cursor location, for StrLen +{ + EFI_INPUT_KEY Key; + EFI_STATUS Status; + UINTN Len; + + if (Prompt) { + ConOut->OutputString (ConOut, Prompt); + } + + Len = 0; + for (; ;) { + WaitForSingleEvent (ConIn->WaitForKey, 0); + + Status = uefi_call_wrapper(ConIn->ReadKeyStroke, 2, ConIn, &Key); + if (EFI_ERROR(Status)) { + DEBUG((D_ERROR, "Input: error return from ReadKey %x\n", Status)); + break; + } + + if (Key.UnicodeChar == '\n' || + Key.UnicodeChar == '\r') { + break; + } + + if (Key.UnicodeChar == '\b') { + if (Len) { + uefi_call_wrapper(ConOut->OutputString, 2, ConOut, L"\b \b"); + Len -= 1; + } + continue; + } + + if (Key.UnicodeChar >= ' ') { + if (Len < StrLen-1) { + InStr[Len] = Key.UnicodeChar; + + InStr[Len+1] = 0; + uefi_call_wrapper(ConOut->OutputString, 2, ConOut, &InStr[Len]); + + Len += 1; + } + continue; + } + } + + InStr[Len] = 0; +} diff --git a/gnu-efi/lib/crc.c b/gnu-efi/lib/crc.c new file mode 100644 index 0000000..4367ed1 --- /dev/null +++ b/gnu-efi/lib/crc.c @@ -0,0 +1,218 @@ +/*++ + +Copyright (c) 1998 Intel Corporation + +Module Name: + + crc.c + +Abstract: + + CRC32 functions + + + +Revision History + +--*/ + +#include "lib.h" + + +UINT32 CRCTable[256] = { + 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, + 0xE963A535, 0x9E6495A3, 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, + 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, 0x1DB71064, 0x6AB020F2, + 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, + 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9, + 0xFA0F3D63, 0x8D080DF5, 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, + 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, 0x35B5A8FA, 0x42B2986C, + 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59, + 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, + 0xCFBA9599, 0xB8BDA50F, 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, + 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D, 0x76DC4190, 0x01DB7106, + 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433, + 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D, + 0x91646C97, 0xE6635C01, 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, + 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, 0x65B0D9C6, 0x12B7E950, + 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65, + 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, + 0xA4D1C46D, 0xD3D6F4FB, 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, + 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, 0x5005713C, 0x270241AA, + 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F, + 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81, + 0xB7BD5C3B, 0xC0BA6CAD, 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, + 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683, 0xE3630B12, 0x94643B84, + 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1, + 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB, + 0x196C3671, 0x6E6B06E7, 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, + 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, 0xD6D6A3E8, 0xA1D1937E, + 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B, + 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, + 0x316E8EEF, 0x4669BE79, 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, + 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, 0xC5BA3BBE, 0xB2BD0B28, + 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D, + 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F, + 0x72076785, 0x05005713, 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, + 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, 0x86D3D2D4, 0xF1D4E242, + 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777, + 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69, + 0x616BFFD3, 0x166CCF45, 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, + 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, 0xAED16A4A, 0xD9D65ADC, + 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9, + 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693, + 0x54DE5729, 0x23D967BF, 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, + 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D + }; + + + +VOID +SetCrc ( + IN OUT EFI_TABLE_HEADER *Hdr + ) +/*++ + +Routine Description: + + Updates the CRC32 value in the table header + +Arguments: + + Hdr - The table to update + +Returns: + + None + +--*/ +{ + SetCrcAltSize (Hdr->HeaderSize, Hdr); +} + +VOID +SetCrcAltSize ( + IN UINTN Size, + IN OUT EFI_TABLE_HEADER *Hdr + ) +/*++ + +Routine Description: + + Updates the CRC32 value in the table header + +Arguments: + + Hdr - The table to update + +Returns: + + None + +--*/ +{ + Hdr->CRC32 = 0; + Hdr->CRC32 = CalculateCrc((UINT8 *)Hdr, Size); +} + + +BOOLEAN +CheckCrc ( + IN UINTN MaxSize, + IN OUT EFI_TABLE_HEADER *Hdr + ) +/*++ + +Routine Description: + + Checks the CRC32 value in the table header + +Arguments: + + Hdr - The table to check + +Returns: + + TRUE if the CRC is OK in the table + +--*/ +{ + return CheckCrcAltSize (MaxSize, Hdr->HeaderSize, Hdr); +} + + + + +BOOLEAN +CheckCrcAltSize ( + IN UINTN MaxSize, + IN UINTN Size, + IN OUT EFI_TABLE_HEADER *Hdr + ) +/*++ + +Routine Description: + + Checks the CRC32 value in the table header + +Arguments: + + Hdr - The table to check + +Returns: + + TRUE if the CRC is OK in the table + +--*/ +{ + UINT32 Crc; + UINT32 OrgCrc; + BOOLEAN f; + + if (Size == 0) { + // + // If header size is 0 CRC will pass so return FALSE here + // + return FALSE; + } + if (MaxSize && Size > MaxSize) { + DEBUG((D_ERROR, "CheckCrc32: Size > MaxSize\n")); + return FALSE; + } + + // clear old crc from header + OrgCrc = Hdr->CRC32; + Hdr->CRC32 = 0; + Crc = CalculateCrc((UINT8 *)Hdr, Size); + + // set restults + Hdr->CRC32 = OrgCrc; + + // return status + f = OrgCrc == (UINT32) Crc; + if (!f) { + DEBUG((D_ERROR, "CheckCrc32: Crc check failed\n")); + } + + return f; +} + + +UINT32 +CalculateCrc ( + UINT8 *pt, + UINTN Size + ) +{ + UINTN Crc; + + // compute crc + Crc = 0xffffffff; + while (Size) { + Crc = (Crc >> 8) ^ CRCTable[(UINT8) Crc ^ *pt]; + pt += 1; + Size -= 1; + } + Crc = Crc ^ 0xffffffff; + return (UINT32)Crc; +} diff --git a/gnu-efi/lib/data.c b/gnu-efi/lib/data.c new file mode 100644 index 0000000..61e9b0d --- /dev/null +++ b/gnu-efi/lib/data.c @@ -0,0 +1,204 @@ +/*++ + +Copyright (c) 1998 Intel Corporation + +Module Name: + + data.c + +Abstract: + + EFI library global data + + + +Revision History + +--*/ + +#include "lib.h" + +// +// LibInitialized - TRUE once InitializeLib() is called for the first time +// + +BOOLEAN LibInitialized = FALSE; + +// +// ImageHandle - Current ImageHandle, as passed to InitializeLib +// +EFI_HANDLE LibImageHandle; + +// +// ST - pointer to the EFI system table +// + +EFI_SYSTEM_TABLE *ST; + +// +// BS - pointer to the boot services table +// + +EFI_BOOT_SERVICES *BS; + + +// +// Default pool allocation type +// + +EFI_MEMORY_TYPE PoolAllocationType = EfiBootServicesData; + +// +// Unicode collation functions that are in use +// + +EFI_UNICODE_COLLATION_INTERFACE LibStubUnicodeInterface = { + LibStubStriCmp, + LibStubMetaiMatch, + LibStubStrLwrUpr, + LibStubStrLwrUpr, + NULL, // FatToStr + NULL, // StrToFat + NULL // SupportedLanguages +}; + +EFI_UNICODE_COLLATION_INTERFACE *UnicodeInterface = &LibStubUnicodeInterface; + +// +// Root device path +// + +EFI_DEVICE_PATH RootDevicePath[] = { + {END_DEVICE_PATH_TYPE, END_ENTIRE_DEVICE_PATH_SUBTYPE, {END_DEVICE_PATH_LENGTH,0}} +}; + +EFI_DEVICE_PATH EndDevicePath[] = { + {END_DEVICE_PATH_TYPE, END_ENTIRE_DEVICE_PATH_SUBTYPE, {END_DEVICE_PATH_LENGTH, 0}} +}; + +EFI_DEVICE_PATH EndInstanceDevicePath[] = { + {END_DEVICE_PATH_TYPE, END_INSTANCE_DEVICE_PATH_SUBTYPE, {END_DEVICE_PATH_LENGTH, 0}} +}; + + +// +// EFI IDs +// + +EFI_GUID gEfiGlobalVariableGuid = EFI_GLOBAL_VARIABLE; +EFI_GUID NullGuid = { 0,0,0,{0,0,0,0,0,0,0,0} }; + +// +// Protocol IDs +// + +EFI_GUID gEfiDevicePathProtocolGuid = EFI_DEVICE_PATH_PROTOCOL_GUID; +EFI_GUID gEfiDevicePathToTextProtocolGuid = EFI_DEVICE_PATH_TO_TEXT_PROTOCOL_GUID; +EFI_GUID gEfiDevicePathFromTextProtocolGuid = EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL_GUID; +EFI_GUID gEfiLoadedImageProtocolGuid = EFI_LOADED_IMAGE_PROTOCOL_GUID; +EFI_GUID gEfiSimpleTextInProtocolGuid = EFI_SIMPLE_TEXT_INPUT_PROTOCOL_GUID; +EFI_GUID gEfiSimpleTextOutProtocolGuid = EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL_GUID; +EFI_GUID gEfiBlockIoProtocolGuid = EFI_BLOCK_IO_PROTOCOL_GUID; +EFI_GUID gEfiBlockIo2ProtocolGuid = EFI_BLOCK_IO2_PROTOCOL_GUID; +EFI_GUID gEfiDiskIoProtocolGuid = EFI_DISK_IO_PROTOCOL_GUID; +EFI_GUID gEfiDiskIo2ProtocolGuid = EFI_DISK_IO2_PROTOCOL_GUID; +EFI_GUID gEfiSimpleFileSystemProtocolGuid = EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID; +EFI_GUID gEfiLoadFileProtocolGuid = EFI_LOAD_FILE_PROTOCOL_GUID; +EFI_GUID gEfiDeviceIoProtocolGuid = EFI_DEVICE_IO_PROTOCOL_GUID; +EFI_GUID gEfiUnicodeCollationProtocolGuid = EFI_UNICODE_COLLATION_PROTOCOL_GUID; +EFI_GUID gEfiSerialIoProtocolGuid = EFI_SERIAL_IO_PROTOCOL_GUID; +EFI_GUID gEfiSimpleNetworkProtocolGuid = EFI_SIMPLE_NETWORK_PROTOCOL_GUID; +EFI_GUID gEfiPxeBaseCodeProtocolGuid = EFI_PXE_BASE_CODE_PROTOCOL_GUID; +EFI_GUID gEfiPxeBaseCodeCallbackProtocolGuid = EFI_PXE_BASE_CODE_CALLBACK_PROTOCOL_GUID; +EFI_GUID gEfiNetworkInterfaceIdentifierProtocolGuid = EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL_GUID; +EFI_GUID gEFiUiInterfaceProtocolGuid = EFI_UI_INTERFACE_PROTOCOL_GUID; +EFI_GUID gEfiPciIoProtocolGuid = EFI_PCI_IO_PROTOCOL_GUID; +EFI_GUID gEfiPciRootBridgeIoProtocolGuid = EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_GUID; +EFI_GUID gEfiDriverBindingProtocolGuid = EFI_DRIVER_BINDING_PROTOCOL_GUID; +EFI_GUID gEfiComponentNameProtocolGuid = EFI_COMPONENT_NAME_PROTOCOL_GUID; +EFI_GUID gEfiComponentName2ProtocolGuid = EFI_COMPONENT_NAME2_PROTOCOL_GUID; +EFI_GUID gEfiHashProtocolGuid = EFI_HASH_PROTOCOL_GUID; +EFI_GUID gEfiPlatformDriverOverrideProtocolGuid = EFI_PLATFORM_DRIVER_OVERRIDE_PROTOCOL_GUID; +EFI_GUID gEfiBusSpecificDriverOverrideProtocolGuid = EFI_BUS_SPECIFIC_DRIVER_OVERRIDE_PROTOCOL_GUID; +EFI_GUID gEfiDriverFamilyOverrideProtocolGuid = EFI_DRIVER_FAMILY_OVERRIDE_PROTOCOL_GUID; +EFI_GUID gEfiEbcProtocolGuid = EFI_EBC_PROTOCOL_GUID; + +// +// File system information IDs +// + +EFI_GUID gEfiFileInfoGuid = EFI_FILE_INFO_ID; +EFI_GUID gEfiFileSystemInfoGuid = EFI_FILE_SYSTEM_INFO_ID; +EFI_GUID gEfiFileSystemVolumeLabelInfoIdGuid = EFI_FILE_SYSTEM_VOLUME_LABEL_INFO_ID; + +// +// Reference implementation public protocol IDs +// + +EFI_GUID InternalShellProtocol = INTERNAL_SHELL_GUID; +EFI_GUID VariableStoreProtocol = VARIABLE_STORE_PROTOCOL; +EFI_GUID LegacyBootProtocol = LEGACY_BOOT_PROTOCOL; +EFI_GUID VgaClassProtocol = VGA_CLASS_DRIVER_PROTOCOL; + +EFI_GUID TextOutSpliterProtocol = TEXT_OUT_SPLITER_PROTOCOL; +EFI_GUID ErrorOutSpliterProtocol = ERROR_OUT_SPLITER_PROTOCOL; +EFI_GUID TextInSpliterProtocol = TEXT_IN_SPLITER_PROTOCOL; +/* Added for GOP support */ +EFI_GUID gEfiGraphicsOutputProtocolGuid = EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID; +EFI_GUID gEfiEdidDiscoveredProtocolGuid = EFI_EDID_DISCOVERED_PROTOCOL_GUID; +EFI_GUID gEfiEdidActiveProtocolGuid = EFI_EDID_ACTIVE_PROTOCOL_GUID; +EFI_GUID gEfiEdidOverrideProtocolGuid = EFI_EDID_OVERRIDE_PROTOCOL_GUID; + +EFI_GUID AdapterDebugProtocol = ADAPTER_DEBUG_PROTOCOL; + +// +// Device path media protocol IDs +// +EFI_GUID gEfiPcAnsiGuid = EFI_PC_ANSI_GUID; +EFI_GUID gEfiVT100Guid = EFI_VT_100_GUID; +EFI_GUID gEfiVT100PlusGuid = EFI_VT_100_PLUS_GUID; +EFI_GUID gEfiVTUTF8Guid = EFI_VT_UTF8_GUID; + +// +// EFI GPT Partition Type GUIDs +// +EFI_GUID EfiPartTypeSystemPartitionGuid = EFI_PART_TYPE_EFI_SYSTEM_PART_GUID; +EFI_GUID EfiPartTypeLegacyMbrGuid = EFI_PART_TYPE_LEGACY_MBR_GUID; + + +// +// Reference implementation Vendor Device Path Guids +// +EFI_GUID UnknownDevice = UNKNOWN_DEVICE_GUID; + +// +// Configuration Table GUIDs +// + +EFI_GUID MpsTableGuid = MPS_TABLE_GUID; +EFI_GUID AcpiTableGuid = ACPI_TABLE_GUID; +EFI_GUID SMBIOSTableGuid = SMBIOS_TABLE_GUID; +EFI_GUID SMBIOS3TableGuid = SMBIOS3_TABLE_GUID; +EFI_GUID SalSystemTableGuid = SAL_SYSTEM_TABLE_GUID; + +// +// Network protocol GUIDs +// +EFI_GUID Ip4ServiceBindingProtocol = EFI_IP4_SERVICE_BINDING_PROTOCOL; +EFI_GUID Ip4Protocol = EFI_IP4_PROTOCOL; +EFI_GUID Udp4ServiceBindingProtocol = EFI_UDP4_SERVICE_BINDING_PROTOCOL; +EFI_GUID Udp4Protocol = EFI_UDP4_PROTOCOL; +EFI_GUID Tcp4ServiceBindingProtocol = EFI_TCP4_SERVICE_BINDING_PROTOCOL; +EFI_GUID Tcp4Protocol = EFI_TCP4_PROTOCOL; + +// +// Pointer protocol GUIDs +// +EFI_GUID SimplePointerProtocol = EFI_SIMPLE_POINTER_PROTOCOL_GUID; +EFI_GUID AbsolutePointerProtocol = EFI_ABSOLUTE_POINTER_PROTOCOL_GUID; + +// +// Debugger protocol GUIDs +// +EFI_GUID gEfiDebugImageInfoTableGuid = EFI_DEBUG_IMAGE_INFO_TABLE_GUID; +EFI_GUID gEfiDebugSupportProtocolGuid = EFI_DEBUG_SUPPORT_PROTOCOL_GUID; diff --git a/gnu-efi/lib/debug.c b/gnu-efi/lib/debug.c new file mode 100644 index 0000000..b635123 --- /dev/null +++ b/gnu-efi/lib/debug.c @@ -0,0 +1,43 @@ +/*++ + +Copyright (c) 1998 Intel Corporation + +Module Name: + + debug.c + +Abstract: + + Debug library functions + + + +Revision History + +--*/ + +#include "lib.h" + + + +// +// Declare runtime functions +// + +// +// +// + +INTN +DbgAssert ( + IN CONST CHAR8 *FileName, + IN INTN LineNo, + IN CONST CHAR8 *Description + ) +{ + DbgPrint (D_ERROR, (CHAR8 *)"%EASSERT FAILED: %a(%d): %a%N\n", FileName, LineNo, Description); + + BREAKPOINT(); + return 0; +} + diff --git a/gnu-efi/lib/dpath.c b/gnu-efi/lib/dpath.c new file mode 100644 index 0000000..5e079d6 --- /dev/null +++ b/gnu-efi/lib/dpath.c @@ -0,0 +1,1262 @@ +/*++ + +Copyright (c) 1998 Intel Corporation + +Module Name: + + dpath.c + +Abstract: + MBR & Device Path functions + + + +Revision History + +2014/04 B.Burette - updated device path text representation, conforming to + UEFI specification 2.4 (dec. 2013). More specifically: + - § 9.3.5: added some media types ie. Sata() + - § 9.6.1.2: Acpi(PNP0A03,0) makes more sense when displayed as PciRoot(0) + - § 9.6.1.5: use commas (instead of '|') between option specific parameters + - § 9.6.1.6: hex values in device paths must be preceded by "0x" or "0X" + +--*/ + +#include "lib.h" + +#define ALIGN_SIZE(a) ((a % MIN_ALIGNMENT_SIZE) ? MIN_ALIGNMENT_SIZE - (a % MIN_ALIGNMENT_SIZE) : 0) + + + +EFI_DEVICE_PATH * +DevicePathFromHandle ( + IN EFI_HANDLE Handle + ) +{ + EFI_STATUS Status; + EFI_DEVICE_PATH *DevicePath; + + Status = uefi_call_wrapper(BS->HandleProtocol, 3, Handle, &DevicePathProtocol, (VOID*)&DevicePath); + if (EFI_ERROR(Status)) { + DevicePath = NULL; + } + + return DevicePath; +} + + +EFI_DEVICE_PATH * +DevicePathInstance ( + IN OUT EFI_DEVICE_PATH **DevicePath, + OUT UINTN *Size + ) +{ + EFI_DEVICE_PATH *Start, *Next, *DevPath; + UINTN Count; + + DevPath = *DevicePath; + Start = DevPath; + + if (!DevPath) { + return NULL; + } + + // + // Check for end of device path type + // + + for (Count = 0; ; Count++) { + Next = NextDevicePathNode(DevPath); + + if (IsDevicePathEndType(DevPath)) { + break; + } + + if (Count > 01000) { + // + // BugBug: Debug code to catch bogus device paths + // + DEBUG((D_ERROR, "DevicePathInstance: DevicePath %x Size %d", *DevicePath, ((UINT8 *) DevPath) - ((UINT8 *) Start) )); + DumpHex (0, 0, ((UINT8 *) DevPath) - ((UINT8 *) Start), Start); + break; + } + + DevPath = Next; + } + + ASSERT (DevicePathSubType(DevPath) == END_ENTIRE_DEVICE_PATH_SUBTYPE || + DevicePathSubType(DevPath) == END_INSTANCE_DEVICE_PATH_SUBTYPE); + + // + // Set next position + // + + if (DevicePathSubType(DevPath) == END_ENTIRE_DEVICE_PATH_SUBTYPE) { + Next = NULL; + } + + *DevicePath = Next; + + // + // Return size and start of device path instance + // + + *Size = ((UINT8 *) DevPath) - ((UINT8 *) Start); + return Start; +} + +UINTN +DevicePathInstanceCount ( + IN EFI_DEVICE_PATH *DevicePath + ) +{ + UINTN Count, Size; + + Count = 0; + while (DevicePathInstance(&DevicePath, &Size)) { + Count += 1; + } + + return Count; +} + + +EFI_DEVICE_PATH * +AppendDevicePath ( + IN EFI_DEVICE_PATH *Src1, + IN EFI_DEVICE_PATH *Src2 + ) +// Src1 may have multiple "instances" and each instance is appended +// Src2 is appended to each instance is Src1. (E.g., it's possible +// to append a new instance to the complete device path by passing +// it in Src2) +{ + UINTN Src1Size, Src1Inst, Src2Size, Size; + EFI_DEVICE_PATH *Dst, *Inst; + UINT8 *DstPos; + + // + // If there's only 1 path, just duplicate it + // + + if (!Src1) { + ASSERT (!IsDevicePathUnpacked (Src2)); + return DuplicateDevicePath (Src2); + } + + if (!Src2) { + ASSERT (!IsDevicePathUnpacked (Src1)); + return DuplicateDevicePath (Src1); + } + + // + // Verify we're not working with unpacked paths + // + +// ASSERT (!IsDevicePathUnpacked (Src1)); +// ASSERT (!IsDevicePathUnpacked (Src2)); + + // + // Append Src2 to every instance in Src1 + // + + Src1Size = DevicePathSize(Src1); + Src1Inst = DevicePathInstanceCount(Src1); + Src2Size = DevicePathSize(Src2); + Size = Src1Size * Src1Inst + Src2Size; + + Dst = AllocatePool (Size); + if (Dst) { + DstPos = (UINT8 *) Dst; + + // + // Copy all device path instances + // + + while ((Inst = DevicePathInstance (&Src1, &Size))) { + + CopyMem(DstPos, Inst, Size); + DstPos += Size; + + CopyMem(DstPos, Src2, Src2Size); + DstPos += Src2Size; + + CopyMem(DstPos, EndInstanceDevicePath, sizeof(EFI_DEVICE_PATH)); + DstPos += sizeof(EFI_DEVICE_PATH); + } + + // Change last end marker + DstPos -= sizeof(EFI_DEVICE_PATH); + CopyMem(DstPos, EndDevicePath, sizeof(EFI_DEVICE_PATH)); + } + + return Dst; +} + + +EFI_DEVICE_PATH * +AppendDevicePathNode ( + IN EFI_DEVICE_PATH *Src1, + IN EFI_DEVICE_PATH *Src2 + ) +// Src1 may have multiple "instances" and each instance is appended +// Src2 is a signal device path node (without a terminator) that is +// appended to each instance is Src1. +{ + EFI_DEVICE_PATH *Temp, *Eop; + UINTN Length; + + // + // Build a Src2 that has a terminator on it + // + + Length = DevicePathNodeLength(Src2); + Temp = AllocatePool (Length + sizeof(EFI_DEVICE_PATH)); + if (!Temp) { + return NULL; + } + + CopyMem (Temp, Src2, Length); + Eop = NextDevicePathNode(Temp); + SetDevicePathEndNode(Eop); + + // + // Append device paths + // + + Src1 = AppendDevicePath (Src1, Temp); + FreePool (Temp); + return Src1; +} + + +EFI_DEVICE_PATH * +FileDevicePath ( + IN EFI_HANDLE Device OPTIONAL, + IN CHAR16 *FileName + ) +/*++ + + N.B. Results are allocated from pool. The caller must FreePool + the resulting device path structure + +--*/ +{ + UINTN Size; + FILEPATH_DEVICE_PATH *FilePath; + EFI_DEVICE_PATH *Eop, *DevicePath; + + Size = StrSize(FileName); + FilePath = AllocateZeroPool (Size + SIZE_OF_FILEPATH_DEVICE_PATH + sizeof(EFI_DEVICE_PATH)); + DevicePath = NULL; + + if (FilePath) { + + // + // Build a file path + // + + FilePath->Header.Type = MEDIA_DEVICE_PATH; + FilePath->Header.SubType = MEDIA_FILEPATH_DP; + SetDevicePathNodeLength (&FilePath->Header, Size + SIZE_OF_FILEPATH_DEVICE_PATH); + CopyMem (FilePath->PathName, FileName, Size); + Eop = NextDevicePathNode(&FilePath->Header); + SetDevicePathEndNode(Eop); + + // + // Append file path to device's device path + // + + DevicePath = (EFI_DEVICE_PATH *) FilePath; + if (Device) { + DevicePath = AppendDevicePath ( + DevicePathFromHandle(Device), + DevicePath + ); + + FreePool(FilePath); + } + } + + return DevicePath; +} + + + +UINTN +DevicePathSize ( + IN EFI_DEVICE_PATH *DevPath + ) +{ + EFI_DEVICE_PATH *Start; + + // + // Search for the end of the device path structure + // + + Start = DevPath; + while (!IsDevicePathEnd(DevPath)) { + DevPath = NextDevicePathNode(DevPath); + } + + // + // Compute the size + // + + return ((UINTN) DevPath - (UINTN) Start) + sizeof(EFI_DEVICE_PATH); +} + +EFI_DEVICE_PATH * +DuplicateDevicePath ( + IN EFI_DEVICE_PATH *DevPath + ) +{ + EFI_DEVICE_PATH *NewDevPath; + UINTN Size; + + + // + // Compute the size + // + + Size = DevicePathSize (DevPath); + + // + // Make a copy + // + + NewDevPath = AllocatePool (Size); + if (NewDevPath) { + CopyMem (NewDevPath, DevPath, Size); + } + + return NewDevPath; +} + +EFI_DEVICE_PATH * +UnpackDevicePath ( + IN EFI_DEVICE_PATH *DevPath + ) +{ + EFI_DEVICE_PATH *Src, *Dest, *NewPath; + UINTN Size; + + // + // Walk device path and round sizes to valid boundries + // + + Src = DevPath; + Size = 0; + for (; ;) { + Size += DevicePathNodeLength(Src); + Size += ALIGN_SIZE(Size); + + if (IsDevicePathEnd(Src)) { + break; + } + + Src = NextDevicePathNode(Src); + } + + + // + // Allocate space for the unpacked path + // + + NewPath = AllocateZeroPool (Size); + if (NewPath) { + + ASSERT (((UINTN)NewPath) % MIN_ALIGNMENT_SIZE == 0); + + // + // Copy each node + // + + Src = DevPath; + Dest = NewPath; + for (; ;) { + Size = DevicePathNodeLength(Src); + CopyMem (Dest, Src, Size); + Size += ALIGN_SIZE(Size); + SetDevicePathNodeLength (Dest, Size); + Dest->Type |= EFI_DP_TYPE_UNPACKED; + Dest = (EFI_DEVICE_PATH *) (((UINT8 *) Dest) + Size); + + if (IsDevicePathEnd(Src)) { + break; + } + + Src = NextDevicePathNode(Src); + } + } + + return NewPath; +} + + +EFI_DEVICE_PATH* +AppendDevicePathInstance ( + IN EFI_DEVICE_PATH *Src, + IN EFI_DEVICE_PATH *Instance + ) +{ + UINT8 *Ptr; + EFI_DEVICE_PATH *DevPath; + UINTN SrcSize; + UINTN InstanceSize; + + if (Src == NULL) { + return DuplicateDevicePath (Instance); + } + SrcSize = DevicePathSize(Src); + InstanceSize = DevicePathSize(Instance); + Ptr = AllocatePool (SrcSize + InstanceSize); + DevPath = (EFI_DEVICE_PATH *)Ptr; + ASSERT(DevPath); + + CopyMem (Ptr, Src, SrcSize); +// FreePool (Src); + + while (!IsDevicePathEnd(DevPath)) { + DevPath = NextDevicePathNode(DevPath); + } + // + // Convert the End to an End Instance, since we are + // appending another instacne after this one its a good + // idea. + // + DevPath->SubType = END_INSTANCE_DEVICE_PATH_SUBTYPE; + + DevPath = NextDevicePathNode(DevPath); + CopyMem (DevPath, Instance, InstanceSize); + return (EFI_DEVICE_PATH *)Ptr; +} + +EFI_STATUS +LibDevicePathToInterface ( + IN EFI_GUID *Protocol, + IN EFI_DEVICE_PATH *FilePath, + OUT VOID **Interface + ) +{ + EFI_STATUS Status; + EFI_HANDLE Device; + + Status = uefi_call_wrapper(BS->LocateDevicePath, 3, Protocol, &FilePath, &Device); + + if (!EFI_ERROR(Status)) { + + // If we didn't get a direct match return not found + Status = EFI_NOT_FOUND; + + if (IsDevicePathEnd(FilePath)) { + + // + // It was a direct match, lookup the protocol interface + // + + Status =uefi_call_wrapper(BS->HandleProtocol, 3, Device, Protocol, Interface); + } + } + + // + // If there was an error, do not return an interface + // + + if (EFI_ERROR(Status)) { + *Interface = NULL; + } + + return Status; +} + +static VOID +_DevPathPci ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath + ) +{ + PCI_DEVICE_PATH *Pci; + + Pci = DevPath; + CatPrint(Str, L"Pci(0x%x,0x%x)", Pci->Device, Pci->Function); +} + +static VOID +_DevPathPccard ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath + ) +{ + PCCARD_DEVICE_PATH *Pccard; + + Pccard = DevPath; + CatPrint(Str, L"Pccard(0x%x)", Pccard-> FunctionNumber ); +} + +static VOID +_DevPathMemMap ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath + ) +{ + MEMMAP_DEVICE_PATH *MemMap; + + MemMap = DevPath; + CatPrint(Str, L"MemMap(%d,0x%x,0x%x)", + MemMap->MemoryType, + MemMap->StartingAddress, + MemMap->EndingAddress + ); +} + +static VOID +_DevPathController ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath + ) +{ + CONTROLLER_DEVICE_PATH *Controller; + + Controller = DevPath; + CatPrint(Str, L"Ctrl(%d)", + Controller->Controller + ); +} + +static VOID +_DevPathVendor ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath + ) +{ + VENDOR_DEVICE_PATH *Vendor; + CHAR16 *Type; + UNKNOWN_DEVICE_VENDOR_DEVICE_PATH *UnknownDevPath; + + Vendor = DevPath; + switch (DevicePathType(&Vendor->Header)) { + case HARDWARE_DEVICE_PATH: Type = L"Hw"; break; + case MESSAGING_DEVICE_PATH: Type = L"Msg"; break; + case MEDIA_DEVICE_PATH: Type = L"Media"; break; + default: Type = L"?"; break; + } + + CatPrint(Str, L"Ven%s(%g", Type, &Vendor->Guid); + if (CompareGuid (&Vendor->Guid, &UnknownDevice) == 0) { + // + // GUID used by EFI to enumerate an EDD 1.1 device + // + UnknownDevPath = (UNKNOWN_DEVICE_VENDOR_DEVICE_PATH *)Vendor; + CatPrint(Str, L":%02x)", UnknownDevPath->LegacyDriveLetter); + } else { + CatPrint(Str, L")"); + } +} + + +/* + Type: 2 (ACPI Device Path) SubType: 1 (ACPI Device Path) + */ +static VOID +_DevPathAcpi ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath + ) +{ + ACPI_HID_DEVICE_PATH *Acpi; + + Acpi = DevPath; + if ((Acpi->HID & PNP_EISA_ID_MASK) == PNP_EISA_ID_CONST) { + switch ( EISA_ID_TO_NUM( Acpi-> HID ) ) { + case 0x301 : { + CatPrint( Str , L"Keyboard(%d)" , Acpi-> UID ) ; + break ; + } + case 0x401 : { + CatPrint( Str , L"ParallelPort(%d)" , Acpi-> UID ) ; + break ; + } + case 0x501 : { + CatPrint( Str , L"Serial(%d)" , Acpi-> UID ) ; + break ; + } + case 0x604 : { + CatPrint( Str , L"Floppy(%d)" , Acpi-> UID ) ; + break ; + } + case 0xa03 : { + CatPrint( Str , L"PciRoot(%d)" , Acpi-> UID ) ; + break ; + } + case 0xa08 : { + CatPrint( Str , L"PcieRoot(%d)" , Acpi-> UID ) ; + break ; + } + default : { + CatPrint( Str , L"Acpi(PNP%04x" , EISA_ID_TO_NUM( Acpi-> HID ) ) ; + if ( Acpi-> UID ) CatPrint( Str , L",%d" , Acpi-> UID ) ; + CatPrint( Str , L")" ) ; + break ; + } + } + } else { + CatPrint( Str , L"Acpi(0x%X" , Acpi-> HID ) ; + if ( Acpi-> UID ) CatPrint( Str , L",%d" , Acpi-> UID ) ; + CatPrint( Str , L")" , Acpi-> HID , Acpi-> UID ) ; + } +} + + +static VOID +_DevPathAtapi ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath + ) +{ + ATAPI_DEVICE_PATH *Atapi; + + Atapi = DevPath; + CatPrint(Str, L"Ata(%s,%s)", + Atapi->PrimarySecondary ? L"Secondary" : L"Primary", + Atapi->SlaveMaster ? L"Slave" : L"Master" + ); +} + +static VOID +_DevPathScsi ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath + ) +{ + SCSI_DEVICE_PATH *Scsi; + + Scsi = DevPath; + CatPrint(Str, L"Scsi(%d,%d)", Scsi->Pun, Scsi->Lun); +} + + +static VOID +_DevPathFibre ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath + ) +{ + FIBRECHANNEL_DEVICE_PATH *Fibre; + + Fibre = DevPath; + CatPrint( Str , L"Fibre%s(0x%016lx,0x%016lx)" , + DevicePathType( & Fibre-> Header ) == MSG_FIBRECHANNEL_DP ? L"" : L"Ex" , + Fibre-> WWN , Fibre-> Lun ) ; +} + +static VOID +_DevPath1394 ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath + ) +{ + F1394_DEVICE_PATH *F1394; + + F1394 = DevPath; + // Guid has format of IEEE-EUI64 + CatPrint(Str, L"I1394(%016lx)", F1394->Guid); +} + + + +static VOID +_DevPathUsb ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath + ) +{ + USB_DEVICE_PATH *Usb; + + Usb = DevPath; + CatPrint( Str , L"Usb(0x%x,0x%x)" , Usb-> Port , Usb-> Endpoint ) ; +} + + +static VOID +_DevPathI2O ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath + ) +{ + I2O_DEVICE_PATH *I2O; + + I2O = DevPath; + CatPrint(Str, L"I2O(0x%X)", I2O->Tid); +} + +static VOID +_DevPathMacAddr ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath + ) +{ + MAC_ADDR_DEVICE_PATH *MAC; + UINTN HwAddressSize; + UINTN Index; + + MAC = DevPath; + + /* HwAddressSize = sizeof(EFI_MAC_ADDRESS); */ + HwAddressSize = DevicePathNodeLength( & MAC-> Header ) ; + HwAddressSize -= sizeof( MAC-> Header ) ; + HwAddressSize -= sizeof( MAC-> IfType ) ; + if (MAC->IfType == 0x01 || MAC->IfType == 0x00) { + HwAddressSize = 6; + } + + CatPrint(Str, L"Mac("); + + for(Index = 0; Index < HwAddressSize; Index++) { + CatPrint(Str, L"%02x",MAC->MacAddress.Addr[Index]); + } + if ( MAC-> IfType != 0 ) { + CatPrint(Str, L",%d" , MAC-> IfType ) ; + } + CatPrint(Str, L")"); +} + +static VOID +CatPrintIPv4( + IN OUT POOL_PRINT * Str , + IN EFI_IPv4_ADDRESS * Address + ) +{ + CatPrint( Str , L"%d.%d.%d.%d" , Address-> Addr[ 0 ] , Address-> Addr[ 1 ] , + Address-> Addr[ 2 ] , Address-> Addr[ 3 ] ) ; +} + +static BOOLEAN +IsNotNullIPv4( + IN EFI_IPv4_ADDRESS * Address + ) +{ + UINT8 val ; + val = Address-> Addr[ 0 ] | Address-> Addr[ 1 ] ; + val |= Address-> Addr[ 2 ] | Address-> Addr[ 3 ] ; + return val != 0 ; +} + +static VOID +CatPrintNetworkProtocol( + IN OUT POOL_PRINT * Str , + IN UINT16 Proto + ) +{ + if ( Proto == 6 ) { + CatPrint( Str , L"TCP" ) ; + } else if ( Proto == 17 ) { + CatPrint( Str , L"UDP" ) ; + } else { + CatPrint( Str , L"%d" , Proto ) ; + } +} + +static VOID +_DevPathIPv4 ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath + ) +{ + IPv4_DEVICE_PATH *IP; + BOOLEAN show ; + + IP = DevPath; + CatPrint( Str , L"IPv4(") ; + CatPrintIPv4( Str , & IP-> RemoteIpAddress ) ; + CatPrint( Str , L",") ; + CatPrintNetworkProtocol( Str , IP-> Protocol ) ; + CatPrint( Str , L",%s" , IP-> StaticIpAddress ? L"Static" : L"DHCP" ) ; + show = IsNotNullIPv4( & IP-> LocalIpAddress ) ; + if ( ! show && DevicePathNodeLength( & IP-> Header ) == sizeof( IPv4_DEVICE_PATH ) ) { + /* only version 2 includes gateway and netmask */ + show |= IsNotNullIPv4( & IP-> GatewayIpAddress ) ; + show |= IsNotNullIPv4( & IP-> SubnetMask ) ; + } + if ( show ) { + CatPrint( Str , L"," ) ; + CatPrintIPv4( Str , & IP-> LocalIpAddress ) ; + if ( DevicePathNodeLength( & IP-> Header ) == sizeof( IPv4_DEVICE_PATH ) ) { + /* only version 2 includes gateway and netmask */ + show = IsNotNullIPv4( & IP-> GatewayIpAddress ) ; + show |= IsNotNullIPv4( & IP-> SubnetMask ) ; + if ( show ) { + CatPrint( Str , L",") ; + CatPrintIPv4( Str , & IP-> GatewayIpAddress ) ; + if ( IsNotNullIPv4( & IP-> SubnetMask ) ) { + CatPrint( Str , L",") ; + CatPrintIPv4( Str , & IP-> SubnetMask ) ; + } + } + } + } + CatPrint( Str , L")") ; +} + +#define CatPrintIPv6_ADD( x , y ) ( ( (UINT16) ( x ) ) << 8 | ( y ) ) +static VOID +CatPrintIPv6( + IN OUT POOL_PRINT * Str , + IN EFI_IPv6_ADDRESS * Address + ) +{ + CatPrint( Str , L"%x:%x:%x:%x:%x:%x:%x:%x" , + CatPrintIPv6_ADD( Address-> Addr[ 0 ] , Address-> Addr[ 1 ] ) , + CatPrintIPv6_ADD( Address-> Addr[ 2 ] , Address-> Addr[ 3 ] ) , + CatPrintIPv6_ADD( Address-> Addr[ 4 ] , Address-> Addr[ 5 ] ) , + CatPrintIPv6_ADD( Address-> Addr[ 6 ] , Address-> Addr[ 7 ] ) , + CatPrintIPv6_ADD( Address-> Addr[ 8 ] , Address-> Addr[ 9 ] ) , + CatPrintIPv6_ADD( Address-> Addr[ 10 ] , Address-> Addr[ 11 ] ) , + CatPrintIPv6_ADD( Address-> Addr[ 12 ] , Address-> Addr[ 13 ] ) , + CatPrintIPv6_ADD( Address-> Addr[ 14 ] , Address-> Addr[ 15 ] ) ) ; +} + +static VOID +_DevPathIPv6 ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath + ) +{ + IPv6_DEVICE_PATH *IP; + + IP = DevPath; + CatPrint( Str , L"IPv6(") ; + CatPrintIPv6( Str , & IP-> RemoteIpAddress ) ; + CatPrint( Str , L",") ; + CatPrintNetworkProtocol( Str, IP-> Protocol ) ; + CatPrint( Str , L",%s," , IP-> IPAddressOrigin ? + ( IP-> IPAddressOrigin == 1 ? L"StatelessAutoConfigure" : + L"StatefulAutoConfigure" ) : L"Static" ) ; + CatPrintIPv6( Str , & IP-> LocalIpAddress ) ; + if ( DevicePathNodeLength( & IP-> Header ) == sizeof( IPv6_DEVICE_PATH ) ) { + CatPrint( Str , L",") ; + CatPrintIPv6( Str , & IP-> GatewayIpAddress ) ; + CatPrint( Str , L",") ; + CatPrint( Str , L"%d" , & IP-> PrefixLength ) ; + } + CatPrint( Str , L")") ; +} + +static VOID +_DevPathUri ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath + ) +{ + URI_DEVICE_PATH *Uri; + + Uri = DevPath; + + CatPrint( Str, L"Uri(%a)", Uri->Uri ); +} + +static VOID +_DevPathInfiniBand ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath + ) +{ + INFINIBAND_DEVICE_PATH *InfiniBand; + + InfiniBand = DevPath; + CatPrint(Str, L"Infiniband(0x%x,%g,0x%lx,0x%lx,0x%lx)", + InfiniBand->ResourceFlags, InfiniBand->PortGid, InfiniBand->ServiceId, + InfiniBand->TargetPortId, InfiniBand->DeviceId); +} + +static VOID +_DevPathUart ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath + ) +{ + UART_DEVICE_PATH *Uart; + CHAR8 Parity; + + Uart = DevPath; + switch (Uart->Parity) { + case 0 : Parity = 'D'; break; + case 1 : Parity = 'N'; break; + case 2 : Parity = 'E'; break; + case 3 : Parity = 'O'; break; + case 4 : Parity = 'M'; break; + case 5 : Parity = 'S'; break; + default : Parity = 'x'; break; + } + + if (Uart->BaudRate == 0) { + CatPrint(Str, L"Uart(DEFAULT,"); + } else { + CatPrint(Str, L"Uart(%ld,", Uart->BaudRate); + } + + if (Uart->DataBits == 0) { + CatPrint(Str, L"DEFAULT,"); + } else { + CatPrint(Str, L"%d,", Uart->DataBits); + } + + CatPrint(Str, L"%c,", Parity); + + switch (Uart->StopBits) { + case 0 : CatPrint(Str, L"D)"); break; + case 1 : CatPrint(Str, L"1)"); break; + case 2 : CatPrint(Str, L"1.5)"); break; + case 3 : CatPrint(Str, L"2)"); break; + default : CatPrint(Str, L"x)"); break; + } +} + +static VOID +_DevPathSata ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath + ) +{ + SATA_DEVICE_PATH * Sata ; + + Sata = DevPath; + CatPrint( Str , L"Sata(0x%x,0x%x,0x%x)" , Sata-> HBAPortNumber , + Sata-> PortMultiplierPortNumber , Sata-> Lun ) ; +} + +static VOID +_DevPathHardDrive ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath + ) +{ + HARDDRIVE_DEVICE_PATH *Hd; + + Hd = DevPath; + switch (Hd->SignatureType) { + case SIGNATURE_TYPE_MBR: + CatPrint(Str, L"HD(%d,MBR,0x%08x)", + Hd->PartitionNumber, + *((UINT32 *)(&(Hd->Signature[0]))) + ); + break; + case SIGNATURE_TYPE_GUID: + CatPrint(Str, L"HD(%d,GPT,%g)", + Hd->PartitionNumber, + (EFI_GUID *) &(Hd->Signature[0]) + ); + break; + default: + CatPrint(Str, L"HD(%d,%d,0)", + Hd->PartitionNumber, + Hd->SignatureType + ); + break; + } +} + +static VOID +_DevPathCDROM ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath + ) +{ + CDROM_DEVICE_PATH *Cd; + + Cd = DevPath; + CatPrint( Str , L"CDROM(0x%x)" , Cd-> BootEntry ) ; +} + +static VOID +_DevPathFilePath ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath + ) +{ + FILEPATH_DEVICE_PATH *Fp; + + Fp = DevPath; + CatPrint(Str, L"%s", Fp->PathName); +} + +static VOID +_DevPathMediaProtocol ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath + ) +{ + MEDIA_PROTOCOL_DEVICE_PATH *MediaProt; + + MediaProt = DevPath; + CatPrint(Str, L"%g", &MediaProt->Protocol); +} + +static VOID +_DevPathBssBss ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath + ) +{ + BBS_BBS_DEVICE_PATH *Bss; + CHAR16 *Type; + + Bss = DevPath; + switch (Bss->DeviceType) { + case BBS_TYPE_FLOPPY: Type = L"Floppy"; break; + case BBS_TYPE_HARDDRIVE: Type = L"Harddrive"; break; + case BBS_TYPE_CDROM: Type = L"CDROM"; break; + case BBS_TYPE_PCMCIA: Type = L"PCMCIA"; break; + case BBS_TYPE_USB: Type = L"Usb"; break; + case BBS_TYPE_EMBEDDED_NETWORK: Type = L"Net"; break; + default: Type = L"?"; break; + } + + CatPrint(Str, L"Bss-%s(%a)", Type, Bss->String); +} + + +static VOID +_DevPathEndInstance ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath EFI_UNUSED + ) +{ + CatPrint(Str, L","); +} + +/** + * Print unknown device node. + * UEFI 2.4 § 9.6.1.6 table 89. + */ + +static VOID +_DevPathNodeUnknown ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath + ) +{ + EFI_DEVICE_PATH * Path ; + UINT8 * value ; + int length , index ; + Path = DevPath ; + value = DevPath ; + value += 4 ; + switch ( Path-> Type ) { + case HARDWARE_DEVICE_PATH : { /* Unknown Hardware Device Path */ + CatPrint( Str , L"HardwarePath(%d" , Path-> SubType ) ; + break ; + } + case ACPI_DEVICE_PATH : { /* Unknown ACPI Device Path */ + CatPrint( Str , L"AcpiPath(%d" , Path-> SubType ) ; + break ; + } + case MESSAGING_DEVICE_PATH : { /* Unknown Messaging Device Path */ + CatPrint( Str , L"Msg(%d" , Path-> SubType ) ; + break ; + } + case MEDIA_DEVICE_PATH : { /* Unknown Media Device Path */ + CatPrint( Str , L"MediaPath(%d" , Path-> SubType ) ; + break ; + } + case BBS_DEVICE_PATH : { /* Unknown BIOS Boot Specification Device Path */ + CatPrint( Str , L"BbsPath(%d" , Path-> SubType ) ; + break ; + } + default : { /* Unknown Device Path */ + CatPrint( Str , L"Path(%d,%d" , Path-> Type , Path-> SubType ) ; + break ; + } + } + length = DevicePathNodeLength( Path ) ; + for ( index = 0 ; index < length ; index ++ ) { + if ( index == 0 ) CatPrint( Str , L",0x" ) ; + CatPrint( Str , L"%02x" , * value ) ; + value ++ ; + } + CatPrint( Str , L")" ) ; +} + + +/* + * Table to convert "Type" and "SubType" to a "convert to text" function/ + * Entries hold "Type" and "SubType" for know values. + * Special "SubType" 0 is used as default for known type with unknown subtype. + */ +struct { + UINT8 Type; + UINT8 SubType; + VOID (*Function)(POOL_PRINT *, VOID *); +} DevPathTable[] = { + { HARDWARE_DEVICE_PATH, HW_PCI_DP, _DevPathPci}, + { HARDWARE_DEVICE_PATH, HW_PCCARD_DP, _DevPathPccard}, + { HARDWARE_DEVICE_PATH, HW_MEMMAP_DP, _DevPathMemMap}, + { HARDWARE_DEVICE_PATH, HW_VENDOR_DP, _DevPathVendor}, + { HARDWARE_DEVICE_PATH, HW_CONTROLLER_DP, _DevPathController}, + { ACPI_DEVICE_PATH, ACPI_DP, _DevPathAcpi}, + { MESSAGING_DEVICE_PATH, MSG_ATAPI_DP, _DevPathAtapi}, + { MESSAGING_DEVICE_PATH, MSG_SCSI_DP, _DevPathScsi}, + { MESSAGING_DEVICE_PATH, MSG_FIBRECHANNEL_DP, _DevPathFibre}, + { MESSAGING_DEVICE_PATH, MSG_1394_DP, _DevPath1394}, + { MESSAGING_DEVICE_PATH, MSG_USB_DP, _DevPathUsb}, + { MESSAGING_DEVICE_PATH, MSG_I2O_DP, _DevPathI2O}, + { MESSAGING_DEVICE_PATH, MSG_MAC_ADDR_DP, _DevPathMacAddr}, + { MESSAGING_DEVICE_PATH, MSG_IPv4_DP, _DevPathIPv4}, + { MESSAGING_DEVICE_PATH, MSG_IPv6_DP, _DevPathIPv6}, + { MESSAGING_DEVICE_PATH, MSG_URI_DP, _DevPathUri}, + { MESSAGING_DEVICE_PATH, MSG_INFINIBAND_DP, _DevPathInfiniBand}, + { MESSAGING_DEVICE_PATH, MSG_UART_DP, _DevPathUart}, + { MESSAGING_DEVICE_PATH , MSG_SATA_DP , _DevPathSata } , + { MESSAGING_DEVICE_PATH, MSG_VENDOR_DP, _DevPathVendor}, + { MEDIA_DEVICE_PATH, MEDIA_HARDDRIVE_DP, _DevPathHardDrive}, + { MEDIA_DEVICE_PATH, MEDIA_CDROM_DP, _DevPathCDROM}, + { MEDIA_DEVICE_PATH, MEDIA_VENDOR_DP, _DevPathVendor}, + { MEDIA_DEVICE_PATH, MEDIA_FILEPATH_DP, _DevPathFilePath}, + { MEDIA_DEVICE_PATH, MEDIA_PROTOCOL_DP, _DevPathMediaProtocol}, + { BBS_DEVICE_PATH, BBS_BBS_DP, _DevPathBssBss}, + { END_DEVICE_PATH_TYPE, END_INSTANCE_DEVICE_PATH_SUBTYPE, _DevPathEndInstance}, + { 0, 0, NULL} +}; + + +CHAR16 * +DevicePathToStr ( + EFI_DEVICE_PATH *DevPath + ) +/*++ + + Turns the Device Path into a printable string. Allcoates + the string from pool. The caller must FreePool the returned + string. + +--*/ +{ + POOL_PRINT Str; + EFI_DEVICE_PATH *DevPathNode; + VOID (*DumpNode)(POOL_PRINT *, VOID *); + UINTN Index, NewSize; + + ZeroMem(&Str, sizeof(Str)); + + // + // Unpacked the device path + // + + DevPath = UnpackDevicePath(DevPath); + ASSERT (DevPath); + + + // + // Process each device path node + // + + DevPathNode = DevPath; + while (!IsDevicePathEnd(DevPathNode)) { + // + // Find the handler to dump this device path node + // + + DumpNode = NULL; + for (Index = 0; DevPathTable[Index].Function; Index += 1) { + + if (DevicePathType(DevPathNode) == DevPathTable[Index].Type && + DevicePathSubType(DevPathNode) == DevPathTable[Index].SubType) { + DumpNode = DevPathTable[Index].Function; + break; + } + } + + // + // If not found, use a generic function + // + + if (!DumpNode) { + DumpNode = _DevPathNodeUnknown; + } + + // + // Put a path seperator in if needed + // + + if (Str.len && DumpNode != _DevPathEndInstance) { + CatPrint (&Str, L"/"); + } + + // + // Print this node of the device path + // + + DumpNode (&Str, DevPathNode); + + // + // Next device path node + // + + DevPathNode = NextDevicePathNode(DevPathNode); + } + + // + // Shrink pool used for string allocation + // + + FreePool (DevPath); + NewSize = (Str.len + 1) * sizeof(CHAR16); + Str.str = ReallocatePool (Str.str, NewSize, NewSize); + Str.str[Str.len] = 0; + return Str.str; +} + +BOOLEAN +LibMatchDevicePaths ( + IN EFI_DEVICE_PATH *Multi, + IN EFI_DEVICE_PATH *Single + ) +{ + EFI_DEVICE_PATH *DevicePath, *DevicePathInst; + UINTN Size; + + if (!Multi || !Single) { + return FALSE; + } + + DevicePath = Multi; + while ((DevicePathInst = DevicePathInstance (&DevicePath, &Size))) { + if (CompareMem (Single, DevicePathInst, Size) == 0) { + return TRUE; + } + } + return FALSE; +} + +EFI_DEVICE_PATH * +LibDuplicateDevicePathInstance ( + IN EFI_DEVICE_PATH *DevPath + ) +{ + EFI_DEVICE_PATH *NewDevPath,*DevicePathInst,*Temp; + UINTN Size = 0; + + // + // get the size of an instance from the input + // + + Temp = DevPath; + DevicePathInst = DevicePathInstance (&Temp, &Size); + + // + // Make a copy and set proper end type + // + NewDevPath = NULL; + if (Size) { + NewDevPath = AllocatePool (Size + sizeof(EFI_DEVICE_PATH)); + } + + if (NewDevPath) { + CopyMem (NewDevPath, DevicePathInst, Size); + Temp = NextDevicePathNode(NewDevPath); + SetDevicePathEndNode(Temp); + } + + return NewDevPath; +} + diff --git a/gnu-efi/lib/error.c b/gnu-efi/lib/error.c new file mode 100644 index 0000000..c4d053d --- /dev/null +++ b/gnu-efi/lib/error.c @@ -0,0 +1,83 @@ +/*++ + +Copyright (c) 1998 Intel Corporation + +Module Name: + + error.c + +Abstract: + + + + +Revision History + +--*/ + +#include "lib.h" + + +struct { + EFI_STATUS Code; + WCHAR *Desc; +} ErrorCodeTable[] = { + { EFI_SUCCESS, L"Success"}, + { EFI_LOAD_ERROR, L"Load Error"}, + { EFI_INVALID_PARAMETER, L"Invalid Parameter"}, + { EFI_UNSUPPORTED, L"Unsupported"}, + { EFI_BAD_BUFFER_SIZE, L"Bad Buffer Size"}, + { EFI_BUFFER_TOO_SMALL, L"Buffer Too Small"}, + { EFI_NOT_READY, L"Not Ready"}, + { EFI_DEVICE_ERROR, L"Device Error"}, + { EFI_WRITE_PROTECTED, L"Write Protected"}, + { EFI_OUT_OF_RESOURCES, L"Out of Resources"}, + { EFI_VOLUME_CORRUPTED, L"Volume Corrupt"}, + { EFI_VOLUME_FULL, L"Volume Full"}, + { EFI_NO_MEDIA, L"No Media"}, + { EFI_MEDIA_CHANGED, L"Media changed"}, + { EFI_NOT_FOUND, L"Not Found"}, + { EFI_ACCESS_DENIED, L"Access Denied"}, + { EFI_NO_RESPONSE, L"No Response"}, + { EFI_NO_MAPPING, L"No mapping"}, + { EFI_TIMEOUT, L"Time out"}, + { EFI_NOT_STARTED, L"Not started"}, + { EFI_ALREADY_STARTED, L"Already started"}, + { EFI_ABORTED, L"Aborted"}, + { EFI_ICMP_ERROR, L"ICMP Error"}, + { EFI_TFTP_ERROR, L"TFTP Error"}, + { EFI_PROTOCOL_ERROR, L"Protocol Error"}, + { EFI_INCOMPATIBLE_VERSION, L"Incompatible Version"}, + { EFI_SECURITY_VIOLATION, L"Security Policy Violation"}, + { EFI_CRC_ERROR, L"CRC Error"}, + { EFI_END_OF_MEDIA, L"End of Media"}, + { EFI_END_OF_FILE, L"End of File"}, + { EFI_INVALID_LANGUAGE, L"Invalid Languages"}, + { EFI_COMPROMISED_DATA, L"Compromised Data"}, + + // warnings + { EFI_WARN_UNKNOWN_GLYPH, L"Warning Unknown Glyph"}, + { EFI_WARN_DELETE_FAILURE, L"Warning Delete Failure"}, + { EFI_WARN_WRITE_FAILURE, L"Warning Write Failure"}, + { EFI_WARN_BUFFER_TOO_SMALL, L"Warning Buffer Too Small"}, + { 0, NULL} +} ; + + +VOID +StatusToString ( + OUT CHAR16 *Buffer, + IN EFI_STATUS Status + ) +{ + UINTN Index; + + for (Index = 0; ErrorCodeTable[Index].Desc; Index +=1) { + if (ErrorCodeTable[Index].Code == Status) { + StrCpy (Buffer, ErrorCodeTable[Index].Desc); + return; + } + } + + SPrint (Buffer, 0, L"%X", Status); +} diff --git a/gnu-efi/lib/event.c b/gnu-efi/lib/event.c new file mode 100644 index 0000000..0babc92 --- /dev/null +++ b/gnu-efi/lib/event.c @@ -0,0 +1,154 @@ +/*++ + +Copyright (c) 1998 Intel Corporation + +Module Name: + + event.c + +Abstract: + + + + +Revision History + +--*/ + +#include "lib.h" + + +EFI_EVENT +LibCreateProtocolNotifyEvent ( + IN EFI_GUID *ProtocolGuid, + IN EFI_TPL NotifyTpl, + IN EFI_EVENT_NOTIFY NotifyFunction, + IN VOID *NotifyContext, + OUT VOID *Registration + ) +{ + EFI_STATUS Status; + EFI_EVENT Event; + + // + // Create the event + // + + Status = uefi_call_wrapper( + BS->CreateEvent, + 5, + EVT_NOTIFY_SIGNAL, + NotifyTpl, + NotifyFunction, + NotifyContext, + &Event + ); + if ( EFI_ERROR( Status ) ) return NULL ; + ASSERT (!EFI_ERROR(Status)); + + // + // Register for protocol notifactions on this event + // + + Status = uefi_call_wrapper( + BS->RegisterProtocolNotify, + 3, + ProtocolGuid, + Event, + Registration + ); + if ( EFI_ERROR( Status ) ) return NULL ; + ASSERT (!EFI_ERROR(Status)); + + // + // Kick the event so we will perform an initial pass of + // current installed drivers + // + + uefi_call_wrapper(BS->SignalEvent, 1, Event); + return Event; +} + + +EFI_STATUS +WaitForSingleEvent ( + IN EFI_EVENT Event, + IN UINT64 Timeout OPTIONAL + ) +{ + EFI_STATUS Status; + UINTN Index; + EFI_EVENT TimerEvent; + EFI_EVENT WaitList[2]; + + if (Timeout) { + // + // Create a timer event + // + + Status = uefi_call_wrapper(BS->CreateEvent, 5, EVT_TIMER, 0, NULL, NULL, &TimerEvent); + if (!EFI_ERROR(Status)) { + + // + // Set the timer event + // + + uefi_call_wrapper(BS->SetTimer, 3, TimerEvent, TimerRelative, Timeout); + + // + // Wait for the original event or the timer + // + + WaitList[0] = Event; + WaitList[1] = TimerEvent; + Status = uefi_call_wrapper(BS->WaitForEvent, 3, 2, WaitList, &Index); + uefi_call_wrapper(BS->CloseEvent, 1, TimerEvent); + + // + // If the timer expired, change the return to timed out + // + + if (!EFI_ERROR(Status) && Index == 1) { + Status = EFI_TIMEOUT; + } + } + + } else { + + // + // No timeout... just wait on the event + // + + Status = uefi_call_wrapper(BS->WaitForEvent, 3, 1, &Event, &Index); + ASSERT (!EFI_ERROR(Status)); + ASSERT (Index == 0); + } + + return Status; +} + +VOID +WaitForEventWithTimeout ( + IN EFI_EVENT Event, + IN UINTN Timeout, + IN UINTN Row, + IN UINTN Column, + IN CHAR16 *String, + IN EFI_INPUT_KEY TimeoutKey, + OUT EFI_INPUT_KEY *Key + ) +{ + EFI_STATUS Status; + + do { + PrintAt (Column, Row, String, Timeout); + Status = WaitForSingleEvent (Event, 10000000); + if (Status == EFI_SUCCESS) { + if (!EFI_ERROR(uefi_call_wrapper(ST->ConIn->ReadKeyStroke, 2, ST->ConIn, Key))) { + return; + } + } + } while (Timeout > 0); + CopyMem(Key, &TimeoutKey, sizeof(EFI_INPUT_KEY)); +} + diff --git a/gnu-efi/lib/exit.c b/gnu-efi/lib/exit.c new file mode 100644 index 0000000..ada27c9 --- /dev/null +++ b/gnu-efi/lib/exit.c @@ -0,0 +1,19 @@ +#include "lib.h" + +VOID +Exit( + IN EFI_STATUS ExitStatus, + IN UINTN ExitDataSize, + IN CHAR16 *ExitData OPTIONAL + ) +{ + uefi_call_wrapper(BS->Exit, + 4, + LibImageHandle, + ExitStatus, + ExitDataSize, + ExitData); + + // Uh oh, Exit() returned?! + for (;;) { } +} diff --git a/gnu-efi/lib/guid.c b/gnu-efi/lib/guid.c new file mode 100644 index 0000000..6498e90 --- /dev/null +++ b/gnu-efi/lib/guid.c @@ -0,0 +1,179 @@ +/*++ + +Copyright (c) 1998 Intel Corporation + +Module Name: + + misc.c + +Abstract: + + Misc EFI support functions + + + +Revision History + +--*/ + +#include "lib.h" + + +// +// Additional Known guids +// + +#define SHELL_INTERFACE_PROTOCOL \ + { 0x47c7b223, 0xc42a, 0x11d2, {0x8e, 0x57, 0x0, 0xa0, 0xc9, 0x69, 0x72, 0x3b} } + +#define ENVIRONMENT_VARIABLE_ID \ + { 0x47c7b224, 0xc42a, 0x11d2, {0x8e, 0x57, 0x0, 0xa0, 0xc9, 0x69, 0x72, 0x3b} } + +#define DEVICE_PATH_MAPPING_ID \ + { 0x47c7b225, 0xc42a, 0x11d2, {0x8e, 0x57, 0x0, 0xa0, 0xc9, 0x69, 0x72, 0x3b} } + +#define PROTOCOL_ID_ID \ + { 0x47c7b226, 0xc42a, 0x11d2, {0x8e, 0x57, 0x0, 0xa0, 0xc9, 0x69, 0x72, 0x3b} } + +#define ALIAS_ID \ + { 0x47c7b227, 0xc42a, 0x11d2, {0x8e, 0x57, 0x0, 0xa0, 0xc9, 0x69, 0x72, 0x3b} } + +static EFI_GUID ShellInterfaceProtocol = SHELL_INTERFACE_PROTOCOL; +static EFI_GUID SEnvId = ENVIRONMENT_VARIABLE_ID; +static EFI_GUID SMapId = DEVICE_PATH_MAPPING_ID; +static EFI_GUID SProtId = PROTOCOL_ID_ID; +static EFI_GUID SAliasId = ALIAS_ID; + +static struct { + EFI_GUID *Guid; + WCHAR *GuidName; +} KnownGuids[] = { + { &NullGuid, L"G0" }, + { &gEfiGlobalVariableGuid, L"EfiVar" }, + + { &VariableStoreProtocol, L"VarStore" }, + { &gEfiDevicePathProtocolGuid, L"DevPath" }, + { &gEfiLoadedImageProtocolGuid, L"LdImg" }, + { &gEfiSimpleTextInProtocolGuid, L"TxtIn" }, + { &gEfiSimpleTextOutProtocolGuid, L"TxtOut" }, + { &gEfiBlockIoProtocolGuid, L"BlkIo" }, + { &gEfiBlockIo2ProtocolGuid, L"BlkIo2" }, + { &gEfiDiskIoProtocolGuid, L"DskIo" }, + { &gEfiDiskIo2ProtocolGuid, L"DskIo2" }, + { &gEfiSimpleFileSystemProtocolGuid, L"Fs" }, + { &gEfiLoadFileProtocolGuid, L"LdFile" }, + { &gEfiDeviceIoProtocolGuid, L"DevIo" }, + { &gEfiComponentNameProtocolGuid, L"CName" }, + { &gEfiComponentName2ProtocolGuid, L"CName2" }, + + { &gEfiFileInfoGuid, L"FileInfo" }, + { &gEfiFileSystemInfoGuid, L"FsInfo" }, + { &gEfiFileSystemVolumeLabelInfoIdGuid, L"FsVolInfo" }, + + { &gEfiUnicodeCollationProtocolGuid, L"Unicode" }, + { &LegacyBootProtocol, L"LegacyBoot" }, + { &gEfiSerialIoProtocolGuid, L"SerIo" }, + { &VgaClassProtocol, L"VgaClass"}, + { &gEfiSimpleNetworkProtocolGuid, L"Net" }, + { &gEfiNetworkInterfaceIdentifierProtocolGuid, L"Nii" }, + { &gEfiPxeBaseCodeProtocolGuid, L"Pxe" }, + { &gEfiPxeBaseCodeCallbackProtocolGuid, L"PxeCb" }, + + { &TextOutSpliterProtocol, L"TxtOutSplit" }, + { &ErrorOutSpliterProtocol, L"ErrOutSplit" }, + { &TextInSpliterProtocol, L"TxtInSplit" }, + { &gEfiPcAnsiGuid, L"PcAnsi" }, + { &gEfiVT100Guid, L"Vt100" }, + { &gEfiVT100PlusGuid, L"Vt100Plus" }, + { &gEfiVTUTF8Guid, L"VtUtf8" }, + { &UnknownDevice, L"UnknownDev" }, + + { &EfiPartTypeSystemPartitionGuid, L"ESP" }, + { &EfiPartTypeLegacyMbrGuid, L"GPT MBR" }, + + { &ShellInterfaceProtocol, L"ShellInt" }, + { &SEnvId, L"SEnv" }, + { &SProtId, L"ShellProtId" }, + { &SMapId, L"ShellDevPathMap" }, + { &SAliasId, L"ShellAlias" }, + + { NULL, L"" } +}; + +// +// +// + +LIST_ENTRY GuidList; + + +VOID +InitializeGuid ( + VOID + ) +{ +} + +INTN +CompareGuid( + IN EFI_GUID *Guid1, + IN EFI_GUID *Guid2 + ) +/*++ + +Routine Description: + + Compares to GUIDs + +Arguments: + + Guid1 - guid to compare + Guid2 - guid to compare + +Returns: + = 0 if Guid1 == Guid2 + +--*/ +{ + return RtCompareGuid (Guid1, Guid2); +} + + +VOID +GuidToString ( + OUT CHAR16 *Buffer, + IN EFI_GUID *Guid + ) +{ + + UINTN Index; + + // + // Else, (for now) use additional internal function for mapping guids + // + + for (Index=0; KnownGuids[Index].Guid; Index++) { + if (CompareGuid(Guid, KnownGuids[Index].Guid) == 0) { + SPrint (Buffer, 0, KnownGuids[Index].GuidName); + return ; + } + } + + // + // Else dump it + // + + SPrint (Buffer, 0, L"%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x", + Guid->Data1, + Guid->Data2, + Guid->Data3, + Guid->Data4[0], + Guid->Data4[1], + Guid->Data4[2], + Guid->Data4[3], + Guid->Data4[4], + Guid->Data4[5], + Guid->Data4[6], + Guid->Data4[7] + ); +} diff --git a/gnu-efi/lib/hand.c b/gnu-efi/lib/hand.c new file mode 100644 index 0000000..6864765 --- /dev/null +++ b/gnu-efi/lib/hand.c @@ -0,0 +1,636 @@ +/*++ + +Copyright (c) 1998 Intel Corporation + +Module Name: + + hand.c + +Abstract: + + + + +Revision History + +--*/ + +#include "lib.h" +#include "efistdarg.h" // !!! + + +EFI_STATUS +LibLocateProtocol ( + IN EFI_GUID *ProtocolGuid, + OUT VOID **Interface + ) +// +// Find the first instance of this Protocol in the system and return it's interface +// +{ + EFI_STATUS Status; + UINTN NumberHandles, Index; + EFI_HANDLE *Handles; + + + *Interface = NULL; + Status = LibLocateHandle (ByProtocol, ProtocolGuid, NULL, &NumberHandles, &Handles); + if (EFI_ERROR(Status)) { + DEBUG((D_INFO, "LibLocateProtocol: Handle not found\n")); + return Status; + } + + for (Index=0; Index < NumberHandles; Index++) { + Status = uefi_call_wrapper(BS->HandleProtocol, 3, Handles[Index], ProtocolGuid, Interface); + if (!EFI_ERROR(Status)) { + break; + } + } + + if (Handles) { + FreePool (Handles); + } + + return Status; +} + +EFI_STATUS +LibLocateHandle ( + IN EFI_LOCATE_SEARCH_TYPE SearchType, + IN EFI_GUID *Protocol OPTIONAL, + IN VOID *SearchKey OPTIONAL, + IN OUT UINTN *NoHandles, + OUT EFI_HANDLE **Buffer + ) + +{ + EFI_STATUS Status; + UINTN BufferSize; + + // + // Initialize for GrowBuffer loop + // + + Status = EFI_SUCCESS; + *Buffer = NULL; + BufferSize = 50 * sizeof(EFI_HANDLE); + + // + // Call the real function + // + + while (GrowBuffer (&Status, (VOID **) Buffer, BufferSize)) { + + Status = uefi_call_wrapper( + BS->LocateHandle, + 5, + SearchType, + Protocol, + SearchKey, + &BufferSize, + *Buffer + ); + + } + + *NoHandles = BufferSize / sizeof (EFI_HANDLE); + if (EFI_ERROR(Status)) { + *NoHandles = 0; + } + + return Status; +} + +EFI_STATUS +LibLocateHandleByDiskSignature ( + IN UINT8 MBRType, + IN UINT8 SignatureType, + IN VOID *Signature, + IN OUT UINTN *NoHandles, + OUT EFI_HANDLE **Buffer + ) + +{ + EFI_STATUS Status; + UINTN BufferSize; + UINTN NoBlockIoHandles; + EFI_HANDLE *BlockIoBuffer; + EFI_DEVICE_PATH *DevicePath; + UINTN Index; + EFI_DEVICE_PATH *Next, *DevPath; + HARDDRIVE_DEVICE_PATH *HardDriveDevicePath; + BOOLEAN Match; + BOOLEAN PreviousNodeIsHardDriveDevicePath; + + // + // Initialize for GrowBuffer loop + // + + Status = EFI_SUCCESS; + BlockIoBuffer = NULL; + BufferSize = 50 * sizeof(EFI_HANDLE); + + // + // Call the real function + // + + while (GrowBuffer (&Status, (VOID **)&BlockIoBuffer, BufferSize)) { + + // + // Get list of device handles that support the BLOCK_IO Protocol. + // + + Status = uefi_call_wrapper( + BS->LocateHandle, + 5, + ByProtocol, + &BlockIoProtocol, + NULL, + &BufferSize, + BlockIoBuffer + ); + + } + + NoBlockIoHandles = BufferSize / sizeof (EFI_HANDLE); + if (EFI_ERROR(Status)) { + NoBlockIoHandles = 0; + } + + // + // If there was an error or there are no device handles that support + // the BLOCK_IO Protocol, then return. + // + + if (NoBlockIoHandles == 0) { + FreePool(BlockIoBuffer); + *NoHandles = 0; + *Buffer = NULL; + return Status; + } + + // + // Loop through all the device handles that support the BLOCK_IO Protocol + // + + *NoHandles = 0; + + for(Index=0;IndexHandleProtocol, + 3, + BlockIoBuffer[Index], + &DevicePathProtocol, + (VOID*)&DevicePath + ); + + // + // Search DevicePath for a Hard Drive Media Device Path node. + // If one is found, then see if it matches the signature that was + // passed in. If it does match, and the next node is the End of the + // device path, and the previous node is not a Hard Drive Media Device + // Path, then we have found a match. + // + + Match = FALSE; + + if (DevicePath != NULL) { + + PreviousNodeIsHardDriveDevicePath = FALSE; + + DevPath = DevicePath; + + // + // Check for end of device path type + // + + for (; ;) { + + if ((DevicePathType(DevPath) == MEDIA_DEVICE_PATH) && + (DevicePathSubType(DevPath) == MEDIA_HARDDRIVE_DP)) { + + HardDriveDevicePath = (HARDDRIVE_DEVICE_PATH *)(DevPath); + + if (PreviousNodeIsHardDriveDevicePath == FALSE) { + + Next = NextDevicePathNode(DevPath); + if (IsDevicePathEndType(Next)) { + if ((HardDriveDevicePath->MBRType == MBRType) && + (HardDriveDevicePath->SignatureType == SignatureType)) { + switch(SignatureType) { + case SIGNATURE_TYPE_MBR: + if (*((UINT32 *)(Signature)) == *(UINT32 *)(&(HardDriveDevicePath->Signature[0]))) { + Match = TRUE; + } + break; + case SIGNATURE_TYPE_GUID: + if (CompareGuid((EFI_GUID *)Signature,(EFI_GUID *)(&(HardDriveDevicePath->Signature[0]))) == 0) { + Match = TRUE; + } + break; + } + } + } + } + PreviousNodeIsHardDriveDevicePath = TRUE; + } else { + PreviousNodeIsHardDriveDevicePath = FALSE; + } + + if (IsDevicePathEnd(DevPath)) { + break; + } + + DevPath = NextDevicePathNode(DevPath); + } + + } + + if (Match == FALSE) { + BlockIoBuffer[Index] = NULL; + } else { + *NoHandles = *NoHandles + 1; + } + } + + // + // If there are no matches, then return + // + + if (*NoHandles == 0) { + FreePool(BlockIoBuffer); + *NoHandles = 0; + *Buffer = NULL; + return EFI_SUCCESS; + } + + // + // Allocate space for the return buffer of device handles. + // + + *Buffer = AllocatePool(*NoHandles * sizeof(EFI_HANDLE)); + + if (*Buffer == NULL) { + FreePool(BlockIoBuffer); + *NoHandles = 0; + *Buffer = NULL; + return EFI_OUT_OF_RESOURCES; + } + + // + // Build list of matching device handles. + // + + *NoHandles = 0; + for(Index=0;IndexHandleProtocol, 3, DeviceHandle, &FileSystemProtocol, (VOID*)&Volume); + + // + // Open the root directory of the volume + // + + if (!EFI_ERROR(Status)) { + Status = uefi_call_wrapper(Volume->OpenVolume, 2, Volume, &File); + } + + // + // Done + // + + return EFI_ERROR(Status) ? NULL : File; +} + +EFI_FILE_INFO * +LibFileInfo ( + IN EFI_FILE_HANDLE FHand + ) +{ + EFI_STATUS Status; + EFI_FILE_INFO *Buffer; + UINTN BufferSize; + + // + // Initialize for GrowBuffer loop + // + + Status = EFI_SUCCESS; + Buffer = NULL; + BufferSize = SIZE_OF_EFI_FILE_INFO + 200; + + // + // Call the real function + // + + while (GrowBuffer (&Status, (VOID **) &Buffer, BufferSize)) { + Status = uefi_call_wrapper( + FHand->GetInfo, + 4, + FHand, + &GenericFileInfo, + &BufferSize, + Buffer + ); + } + + return Buffer; +} + + +EFI_FILE_SYSTEM_INFO * +LibFileSystemInfo ( + IN EFI_FILE_HANDLE FHand + ) +{ + EFI_STATUS Status; + EFI_FILE_SYSTEM_INFO *Buffer; + UINTN BufferSize; + + // + // Initialize for GrowBuffer loop + // + + Status = EFI_SUCCESS; + Buffer = NULL; + BufferSize = SIZE_OF_EFI_FILE_SYSTEM_INFO + 200; + + // + // Call the real function + // + + while (GrowBuffer (&Status, (VOID **) &Buffer, BufferSize)) { + Status = uefi_call_wrapper( + FHand->GetInfo, + 4, + FHand, + &FileSystemInfo, + &BufferSize, + Buffer + ); + } + + return Buffer; +} + +EFI_FILE_SYSTEM_VOLUME_LABEL_INFO * +LibFileSystemVolumeLabelInfo ( + IN EFI_FILE_HANDLE FHand + ) +{ + EFI_STATUS Status; + EFI_FILE_SYSTEM_VOLUME_LABEL_INFO *Buffer; + UINTN BufferSize; + + // + // Initialize for GrowBuffer loop + // + + Status = EFI_SUCCESS; + Buffer = NULL; + BufferSize = SIZE_OF_EFI_FILE_SYSTEM_VOLUME_LABEL_INFO + 200; + + // + // Call the real function + // + + while (GrowBuffer (&Status, (VOID **) &Buffer, BufferSize)) { + Status = uefi_call_wrapper( + FHand->GetInfo, + 4, + FHand, + &FileSystemVolumeLabelInfo, + &BufferSize, + Buffer + ); + } + + return Buffer; +} + + + +EFI_STATUS +LibInstallProtocolInterfaces ( + IN OUT EFI_HANDLE *Handle, + ... + ) +{ + va_list args; + EFI_STATUS Status; + EFI_GUID *Protocol; + VOID *Interface; + EFI_TPL OldTpl; + UINTN Index; + EFI_HANDLE OldHandle; + + // + // Syncronize with notifcations + // + + OldTpl = uefi_call_wrapper(BS->RaiseTPL, 1, TPL_NOTIFY); + OldHandle = *Handle; + + // + // Install the protocol interfaces + // + + Index = 0; + Status = EFI_SUCCESS; + va_start (args, Handle); + + while (!EFI_ERROR(Status)) { + + // + // If protocol is NULL, then it's the end of the list + // + + Protocol = va_arg(args, EFI_GUID *); + if (!Protocol) { + break; + } + + Interface = va_arg(args, VOID *); + + // + // Install it + // + + DEBUG((D_INFO, "LibInstallProtocolInterface: %d %x\n", Protocol, Interface)); + Status = uefi_call_wrapper(BS->InstallProtocolInterface, 4, Handle, Protocol, EFI_NATIVE_INTERFACE, Interface); + if (EFI_ERROR(Status)) { + break; + } + + Index += 1; + } + + // + // If there was an error, remove all the interfaces that were + // installed without any errors + // + + if (EFI_ERROR(Status)) { + va_start (args, Handle); + while (Index) { + + Protocol = va_arg(args, EFI_GUID *); + Interface = va_arg(args, VOID *); + uefi_call_wrapper(BS->UninstallProtocolInterface, 3, *Handle, Protocol, Interface); + + Index -= 1; + } + + *Handle = OldHandle; + } + + // + // Done + // + + uefi_call_wrapper(BS->RestoreTPL, 1, OldTpl); + return Status; +} + + +VOID +LibUninstallProtocolInterfaces ( + IN EFI_HANDLE Handle, + ... + ) +{ + va_list args; + EFI_STATUS Status; + EFI_GUID *Protocol; + VOID *Interface; + + + va_start (args, Handle); + for (; ;) { + + // + // If protocol is NULL, then it's the end of the list + // + + Protocol = va_arg(args, EFI_GUID *); + if (!Protocol) { + break; + } + + Interface = va_arg(args, VOID *); + + // + // Uninstall it + // + + Status = uefi_call_wrapper(BS->UninstallProtocolInterface, 3, Handle, Protocol, Interface); + if (EFI_ERROR(Status)) { + DEBUG((D_ERROR, "LibUninstallProtocolInterfaces: failed %g, %r\n", Protocol, Handle)); + } + } +} + + +EFI_STATUS +LibReinstallProtocolInterfaces ( + IN OUT EFI_HANDLE *Handle, + ... + ) +{ + va_list args; + EFI_STATUS Status; + EFI_GUID *Protocol; + VOID *OldInterface, *NewInterface; + EFI_TPL OldTpl; + UINTN Index; + + // + // Syncronize with notifcations + // + + OldTpl = uefi_call_wrapper(BS->RaiseTPL, 1, TPL_NOTIFY); + + // + // Install the protocol interfaces + // + + Index = 0; + Status = EFI_SUCCESS; + va_start (args, Handle); + + while (!EFI_ERROR(Status)) { + + // + // If protocol is NULL, then it's the end of the list + // + + Protocol = va_arg(args, EFI_GUID *); + if (!Protocol) { + break; + } + + OldInterface = va_arg(args, VOID *); + NewInterface = va_arg(args, VOID *); + + // + // Reinstall it + // + + Status = uefi_call_wrapper(BS->ReinstallProtocolInterface, 4, Handle, Protocol, OldInterface, NewInterface); + if (EFI_ERROR(Status)) { + break; + } + + Index += 1; + } + + // + // If there was an error, undo all the interfaces that were + // reinstalled without any errors + // + + if (EFI_ERROR(Status)) { + va_start (args, Handle); + while (Index) { + + Protocol = va_arg(args, EFI_GUID *); + OldInterface = va_arg(args, VOID *); + NewInterface = va_arg(args, VOID *); + + uefi_call_wrapper(BS->ReinstallProtocolInterface, 4, Handle, Protocol, NewInterface, OldInterface); + + Index -= 1; + } + } + + // + // Done + // + + uefi_call_wrapper(BS->RestoreTPL, 1, OldTpl); + return Status; +} diff --git a/gnu-efi/lib/hw.c b/gnu-efi/lib/hw.c new file mode 100644 index 0000000..09a77f9 --- /dev/null +++ b/gnu-efi/lib/hw.c @@ -0,0 +1,132 @@ +/*++ + +Copyright (c) 1998 Intel Corporation + +Module Name: + + hw.c + +Abstract: + + Debug library functions for Hardware IO access + + + +Revision History + +--*/ + +#include "lib.h" + + +EFI_STATUS +InitializeGlobalIoDevice ( + IN EFI_DEVICE_PATH *DevicePath, + IN EFI_GUID *Protocol, + IN CHAR8 *ErrorStr EFI_UNUSED, + OUT EFI_DEVICE_IO_INTERFACE **GlobalIoFncs + ) +/*++ + +Routine Description: + + Check to see if DevicePath exists for a given Protocol. Return Error if it + exists. Return GlobalIoFuncs set match the DevicePath + + Arguments: + + DevicePath - to operate on + Protocol - to check the DevicePath against + ErrorStr - ASCII string to display on error + GlobalIoFncs - Returned with DeviceIoProtocol for the DevicePath + +Returns: + + Pass or Fail based on wether GlobalIoFncs where found + +--*/ +{ + EFI_STATUS Status; + EFI_HANDLE Handle; + + // + // Check to see if this device path already has Protocol on it. + // if so we are loading recursivly and should exit with an error + // + Status = uefi_call_wrapper(BS->LocateDevicePath, 3, Protocol, &DevicePath, &Handle); + if (!EFI_ERROR(Status)) { + DEBUG ((D_INIT, "Device Already Loaded for %a device\n", ErrorStr)); + return EFI_LOAD_ERROR; + } + + Status = uefi_call_wrapper(BS->LocateDevicePath, 3, &DeviceIoProtocol, &DevicePath, &Handle); + if (!EFI_ERROR(Status)) { + Status = uefi_call_wrapper(BS->HandleProtocol, 3, Handle, &DeviceIoProtocol, (VOID*)GlobalIoFncs); + } + + ASSERT (!EFI_ERROR(Status)); + return Status; +} + +UINT32 +ReadPort ( + IN EFI_DEVICE_IO_INTERFACE *GlobalIoFncs, + IN EFI_IO_WIDTH Width, + IN UINTN Port + ) +{ + UINT32 Data; + EFI_STATUS Status EFI_UNUSED; + + Status = uefi_call_wrapper(GlobalIoFncs->Io.Read, 5, GlobalIoFncs, Width, (UINT64)Port, 1, &Data); + ASSERT(!EFI_ERROR(Status)); + return Data; +} + +UINT32 +WritePort ( + IN EFI_DEVICE_IO_INTERFACE *GlobalIoFncs, + IN EFI_IO_WIDTH Width, + IN UINTN Port, + IN UINTN Data + ) +{ + EFI_STATUS Status EFI_UNUSED; + + Status = uefi_call_wrapper(GlobalIoFncs->Io.Write, 5, GlobalIoFncs, Width, (UINT64)Port, 1, &Data); + ASSERT(!EFI_ERROR(Status)); + return (UINT32)Data; +} + +UINT32 +ReadPciConfig ( + IN EFI_DEVICE_IO_INTERFACE *GlobalIoFncs, + IN EFI_IO_WIDTH Width, + IN UINTN Address + ) +{ + UINT32 Data; + EFI_STATUS Status EFI_UNUSED; + + Status = uefi_call_wrapper(GlobalIoFncs->Pci.Read, 5, GlobalIoFncs, Width, (UINT64)Address, 1, &Data); + ASSERT(!EFI_ERROR(Status)); + return Data; +} + +UINT32 +WritePciConfig ( + IN EFI_DEVICE_IO_INTERFACE *GlobalIoFncs, + IN EFI_IO_WIDTH Width, + IN UINTN Address, + IN UINTN Data + ) +{ + EFI_STATUS Status EFI_UNUSED; + + Status = uefi_call_wrapper(GlobalIoFncs->Pci.Write, 5, GlobalIoFncs, Width, (UINT64)Address, 1, &Data); + ASSERT(!EFI_ERROR(Status)); + return (UINT32)Data; +} + + + diff --git a/gnu-efi/lib/ia32/efi_stub.S b/gnu-efi/lib/ia32/efi_stub.S new file mode 100644 index 0000000..464eae5 --- /dev/null +++ b/gnu-efi/lib/ia32/efi_stub.S @@ -0,0 +1 @@ +/* This stub is a stub to make the build happy */ diff --git a/gnu-efi/lib/ia32/initplat.c b/gnu-efi/lib/ia32/initplat.c new file mode 100644 index 0000000..7c887a6 --- /dev/null +++ b/gnu-efi/lib/ia32/initplat.c @@ -0,0 +1,27 @@ +/*++ + +Copyright (c) 1998 Intel Corporation + +Module Name: + + initplat.c + +Abstract: + + + + +Revision History + +--*/ + +#include "lib.h" + +VOID +InitializeLibPlatform ( + IN EFI_HANDLE ImageHandle EFI_UNUSED, + IN EFI_SYSTEM_TABLE *SystemTable EFI_UNUSED + ) +{ +} + diff --git a/gnu-efi/lib/ia32/math.c b/gnu-efi/lib/ia32/math.c new file mode 100644 index 0000000..fce7a8d --- /dev/null +++ b/gnu-efi/lib/ia32/math.c @@ -0,0 +1,199 @@ +/*++ + +Copyright (c) 1998 Intel Corporation + +Module Name: + + math.c + +Abstract: + + + + +Revision History + +--*/ + +#include "lib.h" + + +// +// Declare runtime functions +// + +#ifdef RUNTIME_CODE +#ifndef __GNUC__ +#pragma RUNTIME_CODE(LShiftU64) +#pragma RUNTIME_CODE(RShiftU64) +#pragma RUNTIME_CODE(MultU64x32) +#pragma RUNTIME_CODE(DivU64x32) +#endif +#endif + +// +// +// + +UINT64 +LShiftU64 ( + IN UINT64 Operand, + IN UINTN Count + ) +// Left shift 64bit by 32bit and get a 64bit result +{ +#ifdef __GNUC__ + return Operand << Count; +#else + UINT64 Result; + _asm { + mov eax, dword ptr Operand[0] + mov edx, dword ptr Operand[4] + mov ecx, Count + and ecx, 63 + + shld edx, eax, cl + shl eax, cl + + cmp ecx, 32 + jc short ls10 + + mov edx, eax + xor eax, eax + +ls10: + mov dword ptr Result[0], eax + mov dword ptr Result[4], edx + } + + return Result; +#endif +} + +UINT64 +RShiftU64 ( + IN UINT64 Operand, + IN UINTN Count + ) +// Right shift 64bit by 32bit and get a 64bit result +{ +#ifdef __GNUC__ + return Operand >> Count; +#else + UINT64 Result; + _asm { + mov eax, dword ptr Operand[0] + mov edx, dword ptr Operand[4] + mov ecx, Count + and ecx, 63 + + shrd eax, edx, cl + shr edx, cl + + cmp ecx, 32 + jc short rs10 + + mov eax, edx + xor edx, edx + +rs10: + mov dword ptr Result[0], eax + mov dword ptr Result[4], edx + } + + return Result; +#endif +} + + +UINT64 +MultU64x32 ( + IN UINT64 Multiplicand, + IN UINTN Multiplier + ) +// Multiple 64bit by 32bit and get a 64bit result +{ +#ifdef __GNUC__ + return Multiplicand * Multiplier; +#else + UINT64 Result; + _asm { + mov eax, dword ptr Multiplicand[0] + mul Multiplier + mov dword ptr Result[0], eax + mov dword ptr Result[4], edx + mov eax, dword ptr Multiplicand[4] + mul Multiplier + add dword ptr Result[4], eax + } + + return Result; +#endif +} + +UINT64 +DivU64x32 ( + IN UINT64 Dividend, + IN UINTN Divisor, + OUT UINTN *Remainder OPTIONAL + ) +// divide 64bit by 32bit and get a 64bit result +// N.B. only works for 31bit divisors!! +{ +#if 0 && defined(__GNUC__) && !defined(__MINGW32__) + if (Remainder) + *Remainder = Dividend % Divisor; + return Dividend / Divisor; +#else + UINT32 Rem; + UINT32 bit; + + ASSERT (Divisor != 0); + ASSERT ((Divisor >> 31) == 0); + + // + // For each bit in the dividend + // + + Rem = 0; + for (bit=0; bit < 64; bit++) { +#if defined(__GNUC__) || defined(__MINGW32__) + asm ( + "shll $1, %0\n\t" + "rcll $1, 4%0\n\t" + "rcll $1, %2\n\t" + "mov %2, %%eax\n\t" + "cmp %1, %%eax\n\t" + "cmc\n\t" + "sbb %%eax, %%eax\n\t" + "sub %%eax, %0\n\t" + "and %1, %%eax\n\t" + "sub %%eax, %2" + : /* no outputs */ + : "m"(Dividend), "m"(Divisor), "m"(Rem) + : "cc","memory","%eax" + ); +#else + _asm { + shl dword ptr Dividend[0], 1 ; shift rem:dividend left one + rcl dword ptr Dividend[4], 1 + rcl dword ptr Rem, 1 + + mov eax, Rem + cmp eax, Divisor ; Is Rem >= Divisor? + cmc ; No - do nothing + sbb eax, eax ; Else, + sub dword ptr Dividend[0], eax ; set low bit in dividen + and eax, Divisor ; and + sub Rem, eax ; subtract divisor + } +#endif + } + + if (Remainder) { + *Remainder = Rem; + } + + return Dividend; +#endif +} diff --git a/gnu-efi/lib/ia32/setjmp.S b/gnu-efi/lib/ia32/setjmp.S new file mode 100644 index 0000000..aa9c084 --- /dev/null +++ b/gnu-efi/lib/ia32/setjmp.S @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved. + * This program and the accompanying materials are licensed and made +available + * under the terms and conditions of the BSD License which accompanies +this + * distribution. The full text of the license may be found at + * http://opensource.org/licenses/bsd-license.php. + * + * THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" +BASIS, + * WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR + * IMPLIED. + */ + .text + .globl setjmp +#ifndef __MINGW32__ + .type setjmp, @function +#else + .def setjmp; .scl 2; .type 32; .endef +#endif +setjmp: + pop %ecx + movl (%esp), %edx + movl %ebx, (%edx) + movl %esi, 4(%edx) + movl %edi, 8(%edx) + movl %ebp, 12(%edx) + movl %esp, 16(%edx) + xorl %eax, %eax + jmp *%ecx + + .globl longjmp +#ifndef __MINGW32__ + .type longjmp, @function +#else + .def longjmp; .scl 2; .type 32; .endef +#endif +longjmp: + pop %eax + pop %edx + pop %eax + movl (%edx), %ebx + movl 4(%edx), %esi + movl 8(%edx), %edi diff --git a/gnu-efi/lib/ia64/initplat.c b/gnu-efi/lib/ia64/initplat.c new file mode 100644 index 0000000..810d4fe --- /dev/null +++ b/gnu-efi/lib/ia64/initplat.c @@ -0,0 +1,30 @@ +/*++ + +Copyright (c) 1999 Intel Corporation + +Module Name: + + initplat.c + +Abstract: + + Functions to make SAL and PAL proc calls + +Revision History + +--*/ +#include "lib.h" + +//#include "palproc.h" + +VOID +InitializeLibPlatform ( + IN EFI_HANDLE ImageHandle EFI_UNUSED, + IN EFI_SYSTEM_TABLE *SystemTable EFI_UNUSED + ) +{ + PLABEL SalPlabel; + UINT64 PalEntry; + + LibInitSalAndPalProc (&SalPlabel, &PalEntry); +} diff --git a/gnu-efi/lib/ia64/math.c b/gnu-efi/lib/ia64/math.c new file mode 100644 index 0000000..a8c4e12 --- /dev/null +++ b/gnu-efi/lib/ia64/math.c @@ -0,0 +1,88 @@ +/*++ + +Copyright (c) 1998 Intel Corporation + +Module Name: + + math.c + +Abstract: + + + + +Revision History + +--*/ + +#include "lib.h" + + +// +// Declare runtime functions +// + +#ifdef RUNTIME_CODE +#ifndef __GNUC__ +#pragma RUNTIME_CODE(LShiftU64) +#pragma RUNTIME_CODE(RShiftU64) +#pragma RUNTIME_CODE(MultU64x32) +#pragma RUNTIME_CODE(DivU64x32) +#endif +#endif + +// +// +// + + + + +UINT64 +LShiftU64 ( + IN UINT64 Operand, + IN UINTN Count + ) +// Left shift 64bit by 32bit and get a 64bit result +{ + return Operand << Count; +} + +UINT64 +RShiftU64 ( + IN UINT64 Operand, + IN UINTN Count + ) +// Right shift 64bit by 32bit and get a 64bit result +{ + return Operand >> Count; +} + + +UINT64 +MultU64x32 ( + IN UINT64 Multiplicand, + IN UINTN Multiplier + ) +// Multiple 64bit by 32bit and get a 64bit result +{ + return Multiplicand * Multiplier; +} + +UINT64 +DivU64x32 ( + IN UINT64 Dividend, + IN UINTN Divisor, + OUT UINTN *Remainder OPTIONAL + ) +// divide 64bit by 32bit and get a 64bit result +// N.B. only works for 31bit divisors!! +{ + ASSERT (Divisor != 0); + + if (Remainder) { + *Remainder = Dividend % Divisor; + } + + return Dividend / Divisor; +} diff --git a/gnu-efi/lib/ia64/palproc.S b/gnu-efi/lib/ia64/palproc.S new file mode 100644 index 0000000..c304a78 --- /dev/null +++ b/gnu-efi/lib/ia64/palproc.S @@ -0,0 +1,161 @@ +//++ +// Copyright (c) 1996-99 Intel Corp. +// +// +// Module Name: +// +// palproc.s +// +// Abstract: +// +// Contains an implementation for making PAL PROC calls on +// IA-64 architecture. +// +// +// +// Revision History: +// +//-- + + .file "palproc.s" + +#include "palproc.h" + + +//----------------------------------------------------------------------------- +//++ +// MakeStaticPALCall +// +// This routine is called whenever an architected static calling convention +// based PAL call is to be made. This call does use RSE actually, but our policy +// in making static PAL calls before memory is available is to make sure that +// we do not nest too deep and allocate beyond 96 banked registers. In other +// words we carefully code calls and control flow before memory is available. +// +// Arguments : All parameters set up to do static PAL call. +// +// On Entry : +// +// Return Value: +// +// As per static calling conventions. +// +//-- +//--------------------------------------------------------------------------- +PROCEDURE_ENTRY(MakeStaticPALCall) + + NESTED_SETUP (5,8,0,0) + mov loc3 = b5 + mov loc4 = r2 + mov loc7 = r1;; + + movl loc6 = PAL_MC_CLEAR_LOG + mov r2 = psr;; + mov loc5 = r2 + + cmp.eq p6,p7 = r28,loc6;; + (p7)movl loc6 = PAL_MC_DYNAMIC_STATE;; + (p7)cmp.eq p6,p7 = r28,loc6;; + + (p7)movl loc6 = PAL_MC_ERROR_INFO;; + (p7)cmp.eq p6,p7 = r28,loc6;; + + (p7)movl loc6 = PAL_MC_RESUME;; + (p7)cmp.eq p6,p7 = r28,loc6 + + mov loc6 = 0x1;; + (p7)dep r2 = loc6,r2,13,1;; // psr.ic = 1 + +// p6 will be true, if it is one of the MCHK calls. There has been lots of debate +// on psr.ic for these values. For now, do not do any thing to psr.ic + +// (p6)dep r2 = r0,r2,13,1;; // psr.ic = 0 + dep r2 = r0,r2,14,1;; // psr.i = 0 + + mov psr.l = r2 + srlz.d;; // Needs data serailization. + srlz.i;; // Needs instruction serailization. + +StaticGetPALLocalIP: + mov loc2 = ip;; + add loc2 = StaticComeBackFromPALCall - StaticGetPALLocalIP,loc2;; + mov b0 = loc2 // return address after Pal call + mov r28 = in1 // get the input parameters to PAL call + mov r29 = in2 + mov r30 = in3;; + mov r31 = in4 + mov b5 = in0;; // get the PalProcEntrypt from input + br.sptk b5 // Take the plunge. + +StaticComeBackFromPALCall: + + mov psr.l = loc5;; + srlz.d;; // Needs data serailization. + srlz.i;; // Needs instruction serailization. + + mov b5 = loc3 + mov r2 = loc4 + mov r1 = loc7 + + NESTED_RETURN + +PROCEDURE_EXIT(MakeStaticPALCall) + + +//----------------------------------------------------------------------------- +//++ +// MakeStackedPALCall +// +// This routine is called whenever an architected stacked calling convention +// based PAL call is to be made. This call is made after memory is available. +// Although stacked calls could be made directly from 'C', there is a PAL +// requirement which forces the index to be in GR28 and hence this stub is +// needed +// +// Arguments : All parameters set up to do stacted PAL call. +// +// On Entry : +// in0: PAL_PROC entrypoint +// in1-in4 : PAL_PROC arguments +// +// Return Value: +// +// As per stacked calling conventions. +// +//-- +//--------------------------------------------------------------------------- +PROCEDURE_ENTRY(MakeStackedPALCall) + + NESTED_SETUP (5,8,4,0) + mov loc3 = b5 + mov loc4 = r2 + mov loc7 = r1 + mov r2 = psr;; + mov loc5 = r2;; + dep r2 = r0,r2,14,1;; // psr.i = 0 + mov psr.l = r2 + srlz.d;; // Needs data serailization. + srlz.i;; // Needs instruction serailization. + +StackedGetPALLocalIP: + mov r28 = in1 // get the input parameters to PAL call + mov out0 = in1 + mov out1 = in2;; + mov out2 = in3 + mov out3 = in4 + mov b5 = in0;; // get the PalProcEntrypt from input + br.call.dpnt b0=b5;; // Take the plunge. + +StackedComeBackFromPALCall: + + mov psr.l = loc5;; + srlz.d;; // Needs data serailization. + srlz.i;; // Needs instruction serailization. + mov b5 = loc3 + mov r2 = loc4 + mov r1 = loc7 + + NESTED_RETURN + +PROCEDURE_EXIT(MakeStackedPALCall) + diff --git a/gnu-efi/lib/ia64/palproc.h b/gnu-efi/lib/ia64/palproc.h new file mode 100644 index 0000000..240946d --- /dev/null +++ b/gnu-efi/lib/ia64/palproc.h @@ -0,0 +1,51 @@ +// +// +// Copyright (c) 1996-99 Intel Corp. +// +// +//Module Name: +// +// palproc.h +// +//Abstract: +// +// This module contains generic macros for an IA64 assembly writer. +// +// +//Revision History +// + +#ifndef _PALPROC_H +#define _PALPROC_H + +#define PROCEDURE_ENTRY(name) .##text; \ + .##type name, @function; \ + .##global name; \ + .##proc name; \ +name: + +#define PROCEDURE_EXIT(name) .##endp name + +// Note: use of NESTED_SETUP requires number of locals (l) >= 3 + +#define NESTED_SETUP(i,l,o,r) \ + alloc loc1=ar##.##pfs,i,l,o,r ;\ + mov loc0=b0 + +#define NESTED_RETURN \ + mov b0=loc0 ;\ + mov ar##.##pfs=loc1 ;;\ + br##.##ret##.##dpnt b0;; + + +// defines needed in palproc.s + +#define PAL_MC_CLEAR_LOG 0x0015 +#define PAL_MC_DRAIN 0x0016 +#define PAL_MC_EXPECTED 0x0017 +#define PAL_MC_DYNAMIC_STATE 0x0018 +#define PAL_MC_ERROR_INFO 0x0019 +#define PAL_MC_RESUME 0x001a +#define PAL_MC_REGISTER_MEM 0x001b + +#endif // _PALPROC_H diff --git a/gnu-efi/lib/ia64/salpal.c b/gnu-efi/lib/ia64/salpal.c new file mode 100644 index 0000000..3d808f3 --- /dev/null +++ b/gnu-efi/lib/ia64/salpal.c @@ -0,0 +1,335 @@ +/*++ + +Copyright (c) 1999 Intel Corporation + +Module Name: + + salpal.c + +Abstract: + + Functions to make SAL and PAL proc calls + +Revision History + +--*/ +#include "lib.h" +#include "palproc.h" +#include "salproc.h" +/*++ + +Copyright (c) 1999 Intel Corporation + +Module Name: + + EfiRtLib.h + +Abstract: + + EFI Runtime library functions + + + +Revision History + +--*/ + +#include "efi.h" +#include "efilib.h" + +rArg +MakeStaticPALCall ( + IN UINT64 PALPROCPtr, + IN UINT64 Arg1, + IN UINT64 Arg2, + IN UINT64 Arg3, + IN UINT64 Arg4 + ); + +rArg +MakeStackedPALCall ( + IN UINT64 PALPROCPtr, + IN UINT64 Arg1, + IN UINT64 Arg2, + IN UINT64 Arg3, + IN UINT64 Arg4 + ); + + +PLABEL SalProcPlabel; +PLABEL PalProcPlabel; +CALL_SAL_PROC GlobalSalProc; +CALL_PAL_PROC GlobalPalProc; + +VOID +LibInitSalAndPalProc ( + OUT PLABEL *SalPlabel, + OUT UINT64 *PalEntry + ) +{ + SAL_SYSTEM_TABLE_ASCENDING_ORDER *SalSystemTable; + EFI_STATUS Status; + + GlobalSalProc = NULL; + GlobalPalProc = NULL; + + Status = LibGetSystemConfigurationTable(&SalSystemTableGuid, (VOID **)&SalSystemTable); + if (EFI_ERROR(Status)) { + return; + } + + // + // BugBug: Add code to test checksum on the Sal System Table + // + if (SalSystemTable->Entry0.Type != 0) { + return; + } + + SalProcPlabel.ProcEntryPoint = SalSystemTable->Entry0.SalProcEntry; + SalProcPlabel.GP = SalSystemTable->Entry0.GlobalDataPointer; + GlobalSalProc = (CALL_SAL_PROC)&SalProcPlabel.ProcEntryPoint; + + // + // Need to check the PAL spec to make sure I'm not responsible for + // storing more state. + // We are passing in a Plabel that should be ignorred by the PAL. Call + // this way will cause use to retore our gp after the PAL returns. + // + PalProcPlabel.ProcEntryPoint = SalSystemTable->Entry0.PalProcEntry; + PalProcPlabel.GP = SalSystemTable->Entry0.GlobalDataPointer; + GlobalPalProc = (CALL_PAL_PROC)PalProcPlabel.ProcEntryPoint; + + *PalEntry = PalProcPlabel.ProcEntryPoint; + *SalPlabel = SalProcPlabel; +} + +EFI_STATUS +LibGetSalIoPortMapping ( + OUT UINT64 *IoPortMapping + ) +/*++ + + Get the IO Port Map from the SAL System Table. + DO NOT USE THIS TO DO YOU OWN IO's!!!!!!!!!!!! + Only use this for getting info, or initing the built in EFI IO abstraction. + Always use the EFI Device IO protoocl to access IO space. + +--*/ +{ + SAL_SYSTEM_TABLE_ASCENDING_ORDER *SalSystemTable; + SAL_ST_MEMORY_DESCRIPTOR_ENTRY *SalMemDesc; + EFI_STATUS Status; + + Status = LibGetSystemConfigurationTable(&SalSystemTableGuid, (VOID **)&SalSystemTable); + if (EFI_ERROR(Status)) { + return EFI_UNSUPPORTED; + } + + // + // BugBug: Add code to test checksum on the Sal System Table + // + if (SalSystemTable->Entry0.Type != 0) { + return EFI_UNSUPPORTED; + } + + // + // The SalSystemTable pointer includes the Type 0 entry. + // The SalMemDesc is Type 1 so it comes next. + // + SalMemDesc = (SAL_ST_MEMORY_DESCRIPTOR_ENTRY *)(SalSystemTable + 1); + while (SalMemDesc->Type == SAL_ST_MEMORY_DESCRIPTOR) { + if (SalMemDesc->MemoryType == SAL_IO_PORT_MAPPING) { + *IoPortMapping = SalMemDesc->PhysicalMemoryAddress; + return EFI_SUCCESS; + } + SalMemDesc++; + } + return EFI_UNSUPPORTED; +} + +EFI_STATUS +LibGetSalIpiBlock ( + OUT UINT64 *IpiBlock + ) +/*++ + + Get the IPI block from the SAL system table + +--*/ +{ + SAL_SYSTEM_TABLE_ASCENDING_ORDER *SalSystemTable; + SAL_ST_MEMORY_DESCRIPTOR_ENTRY *SalMemDesc; + EFI_STATUS Status; + + Status = LibGetSystemConfigurationTable(&SalSystemTableGuid, (VOID*)&SalSystemTable); + if (EFI_ERROR(Status)) { + return EFI_UNSUPPORTED; + } + + // + // BugBug: Add code to test checksum on the Sal System Table + // + if (SalSystemTable->Entry0.Type != 0) { + return EFI_UNSUPPORTED; + } + + // + // The SalSystemTable pointer includes the Type 0 entry. + // The SalMemDesc is Type 1 so it comes next. + // + SalMemDesc = (SAL_ST_MEMORY_DESCRIPTOR_ENTRY *)(SalSystemTable + 1); + while (SalMemDesc->Type == SAL_ST_MEMORY_DESCRIPTOR) { + if (SalMemDesc->MemoryType == SAL_SAPIC_IPI_BLOCK ) { + *IpiBlock = SalMemDesc->PhysicalMemoryAddress; + return EFI_SUCCESS; + } + SalMemDesc++; + } + return EFI_UNSUPPORTED; +} + +EFI_STATUS +LibGetSalWakeupVector ( + OUT UINT64 *WakeVector + ) +/*++ + +Get the wakeup vector from the SAL system table + +--*/ +{ + SAL_ST_AP_WAKEUP_DECRIPTOR *ApWakeUp; + + ApWakeUp = LibSearchSalSystemTable (SAL_ST_AP_WAKEUP); + if (!ApWakeUp) { + *WakeVector = -1; + return EFI_UNSUPPORTED; + } + *WakeVector = ApWakeUp->ExternalInterruptVector; + return EFI_SUCCESS; +} + +VOID * +LibSearchSalSystemTable ( + IN UINT8 EntryType + ) +{ + EFI_STATUS Status; + UINT8 *SalTableHack; + SAL_SYSTEM_TABLE_ASCENDING_ORDER *SalSystemTable; + UINT16 EntryCount; + UINT16 Count; + + Status = LibGetSystemConfigurationTable(&SalSystemTableGuid, (VOID*)&SalSystemTable); + if (EFI_ERROR(Status)) { + return NULL; + } + + EntryCount = SalSystemTable->Header.EntryCount; + if (EntryCount == 0) { + return NULL; + } + // + // BugBug: Add code to test checksum on the Sal System Table + // + + SalTableHack = (UINT8 *)&SalSystemTable->Entry0; + for (Count = 0; Count < EntryCount ;Count++) { + if (*SalTableHack == EntryType) { + return (VOID *)SalTableHack; + } + switch (*SalTableHack) { + case SAL_ST_ENTRY_POINT: + SalTableHack += 48; + break; + case SAL_ST_MEMORY_DESCRIPTOR: + SalTableHack += 32; + break; + case SAL_ST_PLATFORM_FEATURES: + SalTableHack += 16; + break; + case SAL_ST_TR_USAGE: + SalTableHack += 32; + break; + case SAL_ST_PTC: + SalTableHack += 16; + break; + case SAL_ST_AP_WAKEUP: + SalTableHack += 16; + break; + default: + ASSERT(FALSE); + break; + } + } + return NULL; +} + +VOID +LibSalProc ( + IN UINT64 Arg1, + IN UINT64 Arg2, + IN UINT64 Arg3, + IN UINT64 Arg4, + IN UINT64 Arg5, + IN UINT64 Arg6, + IN UINT64 Arg7, + IN UINT64 Arg8, + OUT rArg *Results OPTIONAL + ) +{ + rArg ReturnValue; + + ReturnValue.p0 = -3; // SAL status return completed with error + if (GlobalSalProc) { + ReturnValue = GlobalSalProc(Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7, Arg8); + } + + if (Results) { + CopyMem (Results, &ReturnValue, sizeof(rArg)); + } +} + +VOID +LibPalProc ( + IN UINT64 Arg1, // Pal Proc index + IN UINT64 Arg2, + IN UINT64 Arg3, + IN UINT64 Arg4, + OUT rArg *Results OPTIONAL + ) +{ + + rArg ReturnValue; + + ReturnValue.p0 = -3; // PAL status return completed with error + + // + // check for valid PalProc entry point + // + + if (!GlobalPalProc) { + if (Results) + CopyMem (Results, &ReturnValue, sizeof(rArg)); + return; + } + + // + // check if index falls within stacked or static register calling conventions + // and call appropriate Pal stub call + // + + if (((Arg1 >=255) && (Arg1 <=511)) || + ((Arg1 >=768) && (Arg1 <=1023))) { + ReturnValue = MakeStackedPALCall((UINT64)GlobalPalProc,Arg1,Arg2,Arg3,Arg4); + } + else { + ReturnValue = MakeStaticPALCall((UINT64)GlobalPalProc,Arg1,Arg2,Arg3,Arg4); + } + + if (Results) + CopyMem (Results, &ReturnValue, sizeof(rArg)); + + return; +} + diff --git a/gnu-efi/lib/ia64/setjmp.S b/gnu-efi/lib/ia64/setjmp.S new file mode 100644 index 0000000..bbb29d8 --- /dev/null +++ b/gnu-efi/lib/ia64/setjmp.S @@ -0,0 +1,199 @@ +/* + * Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved. + * This program and the accompanying materials are licensed and made +available + * under the terms and conditions of the BSD License which accompanies +this + * distribution. The full text of the license may be found at + * http://opensource.org/licenses/bsd-license.php. + * + * THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" +BASIS, + * WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR + * IMPLIED. + */ + .text + .globl setjmp + .type setjmp, @function +setjmp: + alloc loc0 = ar.pfs, 1, 2, 1, 0 + ;; + mov r14 = ar.unat + mov r15 = ar.bsp + add r10 = 0x10*20, in0 + ;; + stf.spill.nta [in0] = f2, 0x10 + st8.spill.nta [r10] = r4, 8 + mov r21 = b1 + ;; + stf.spill.nta [in0] = f3, 0x10 + st8.spill.nta [r10] = r5, 8 + mov r22 = b2 + ;; + stf.spill.nta [in0] = f4, 0x10 + st8.spill.nta [r10] = r6, 8 + mov r23 = b3 + ;; + stf.spill.nta [in0] = f5, 0x10 + st8.spill.nta [r10] = r7, 8 + mov r24 = b4 + ;; + stf.spill.nta [in0] = f16, 0x10 + st8.spill.nta [r10] = sp, 8 + mov r25 = b5 + ;; + stf.spill.nta [in0] = f17, 0x10 + st8.nta [r10] = loc1, 8 + mov r16 = pr + ;; + stf.spill.nta [in0] = f18, 0x10 + st8.nta [r10] = r21, 8 + mov r17 = ar.lc + ;; + stf.spill.nta [in0] = f19, 0x10 + st8.nta [r10] = r22, 8 + ;; + stf.spill.nta [in0] = f20, 0x10 + st8.nta [r10] = r23, 8 + ;; + stf.spill.nta [in0] = f21, 0x10 + st8.nta [r10] = r24, 8 + ;; + stf.spill.nta [in0] = f22, 0x10 + st8.nta [r10] = r25, 8 + ;; + stf.spill.nta [in0] = f23, 0x10 + mov r18 = ar.unat + ;; + stf.spill.nta [in0] = f24, 0x10 + st8.nta [r10] = r14, 8 + ;; + stf.spill.nta [in0] = f25, 0x10 + st8.nta [r10] = r18, 8 + ;; + stf.spill.nta [in0] = f26, 0x10 + st8.nta [r10] = loc0, 8 + ;; + stf.spill.nta [in0] = f27, 0x10 + st8.nta [r10] = r15, 8 + mov r8 = 0 + ;; + stf.spill.nta [in0] = f28, 0x10 + mov r19 = ar.fpsr + ;; + stf.spill.nta [in0] = f29, 0x10 + st8.nta [r10] = r16, 8 + mov ar.pfs = loc0 + ;; + stf.spill.nta [in0] = f30, 0x10 + st8.nta [r10] = r17, 8 + mov b0 = loc1 + ;; + stf.spill.nta [in0] = f31, 0x10 + st8.nta [r10] = r19 + ;; + mov ar.unat = r14 + br.ret.sptk b0 + ;; + + .globl longjmp + .type longjmp, @function + .regstk 2, 0, 0, 0 +longjmp: + add r10 = 0x10*20 + 8*14, in0 + movl r2 = ~((((1<<14) - 1) << 16) | 3) + ;; + ld8.nt1 r14 = [r10], -8*2 + mov r15 = ar.bspstore + ;; + ld8.nt1 r17 = [r10], -8 + mov r16 = ar.rsc + cmp.leu p6 = r14, r15 + ;; + ld8.nt1 r18 = [r10], -8 + ld8.nt1 r25 = [r10], -8 + and r2 = r16, r2 + ;; + ldf.fill.nt1 f2 = [in0], 0x10 + ld8.nt1 r24 = [r10], -8 + mov b5 = r25 + ;; + mov ar.rsc = r2 + ld8.nt1 r23 = [r10], -8 + mov b4 = r24 + ;; + ldf.fill.nt1 f3 = [in0], 0x10 + mov ar.unat = r17 +(p6) br.spnt.many _skip_flushrs + ;; + flushrs + mov r15 = ar.bsp + ;; +_skip_flushrs: + mov r31 = ar.rnat + loadrs + ;; + ldf.fill.nt1 f4 = [in0], 0x10 + ld8.nt1 r22 = [r10], -8 + dep r2 = -1, r14, 3, 6 + ;; + ldf.fill.nt1 f5 = [in0], 0x10 + ld8.nt1 r21 = [r10], -8 + cmp.ltu p6 = r2, r15 + ;; + ld8.nt1 r20 = [r10], -0x10 +(p6) ld8.nta r31 = [r2] + mov b3 = r23 + ;; + ldf.fill.nt1 f16 = [in0], 0x10 + ld8.fill.nt1 r7 = [r10], -8 + mov b2 = r22 + ;; + ldf.fill.nt1 f17 = [in0], 0x10 + ld8.fill.nt1 r6 = [r10], -8 + mov b1 = r21 + ;; + ldf.fill.nt1 f18 = [in0], 0x10 + ld8.fill.nt1 r5 = [r10], -8 + mov b0 = r20 + ;; + ldf.fill.nt1 f19 = [in0], 0x10 + ld8.fill.nt1 r4 = [r10], 8*13 + ;; + ldf.fill.nt1 f20 = [in0], 0x10 + ld8.nt1 r19 = [r10], 0x10 + ;; + ldf.fill.nt1 f21 = [in0], 0x10 + ld8.nt1 r26 = [r10], 8 + mov ar.pfs = r19 + ;; + ldf.fill.nt1 f22 = [in0], 0x10 + ld8.nt1 r27 = [r10], 8 + mov pr = r26, -1 + ;; + ldf.fill.nt1 f23 = [in0], 0x10 + ld8.nt1 r28 = [r10], -17*8 - 0x10 + mov ar.lc = r27 + ;; + ldf.fill.nt1 f24 = [in0], 0x10 + ldf.fill.nt1 f25 = [in0], 0x10 + mov r8 = in1 + ;; + ldf.fill.nt1 f26 = [in0], 0x10 + ldf.fill.nt1 f31 = [r10], -0x10 + ;; + ldf.fill.nt1 f27 = [in0], 0x10 + ldf.fill.nt1 f30 = [r10], -0x10 + ;; + ldf.fill.nt1 f28 = [in0] + ldf.fill.nt1 f29 = [r10], 0x10*3 + 8*4 + ;; + ld8.fill.nt1 sp = [r10] + mov ar.unat = r18 + ;; + mov ar.bspstore = r14 + mov ar.rnat = r31 + ;; + invala + mov ar.rsc = r16 + br.ret.sptk b0 diff --git a/gnu-efi/lib/init.c b/gnu-efi/lib/init.c new file mode 100644 index 0000000..4f238c0 --- /dev/null +++ b/gnu-efi/lib/init.c @@ -0,0 +1,214 @@ +/*++ + +Copyright (c) 1998 Intel Corporation + +Module Name: + + +Abstract: + + + + +Revision History + +--*/ + +#include "lib.h" + +VOID +EFIDebugVariable ( + VOID + ); + +VOID +InitializeLib ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +/*++ + +Routine Description: + + Initializes EFI library for use + +Arguments: + + Firmware's EFI system table + +Returns: + + None + +--*/ +{ + EFI_LOADED_IMAGE *LoadedImage; + EFI_STATUS Status; + CHAR8 *LangCode; + + if (!LibInitialized) { + LibInitialized = TRUE; + LibFwInstance = FALSE; + LibImageHandle = ImageHandle; + + + // + // Set up global pointer to the system table, boot services table, + // and runtime services table + // + + ST = SystemTable; + BS = SystemTable->BootServices; + RT = SystemTable->RuntimeServices; +// ASSERT (CheckCrc(0, &ST->Hdr)); +// ASSERT (CheckCrc(0, &BS->Hdr)); +// ASSERT (CheckCrc(0, &RT->Hdr)); + + + // + // Initialize pool allocation type + // + + if (ImageHandle) { + Status = uefi_call_wrapper( + BS->HandleProtocol, + 3, + ImageHandle, + &LoadedImageProtocol, + (VOID*)&LoadedImage + ); + + if (!EFI_ERROR(Status)) { + PoolAllocationType = LoadedImage->ImageDataType; + } + EFIDebugVariable (); + } + + // + // Initialize Guid table + // + + InitializeGuid(); + + InitializeLibPlatform(ImageHandle,SystemTable); + } + + // + // + // + + if (ImageHandle && UnicodeInterface == &LibStubUnicodeInterface) { + LangCode = LibGetVariable (VarLanguage, &EfiGlobalVariable); + InitializeUnicodeSupport (LangCode); + if (LangCode) { + FreePool (LangCode); + } + } +} + +VOID +InitializeUnicodeSupport ( + CHAR8 *LangCode + ) +{ + EFI_UNICODE_COLLATION_INTERFACE *Ui; + EFI_STATUS Status; + CHAR8 *Languages; + UINTN Index, Position, Length; + UINTN NoHandles; + EFI_HANDLE *Handles; + + // + // If we don't know it, lookup the current language code + // + + LibLocateHandle (ByProtocol, &UnicodeCollationProtocol, NULL, &NoHandles, &Handles); + if (!LangCode || !NoHandles) { + goto Done; + } + + // + // Check all driver's for a matching language code + // + + for (Index=0; Index < NoHandles; Index++) { + Status = uefi_call_wrapper(BS->HandleProtocol, 3, Handles[Index], &UnicodeCollationProtocol, (VOID*)&Ui); + if (EFI_ERROR(Status)) { + continue; + } + + // + // Check for a matching language code + // + + Languages = Ui->SupportedLanguages; + Length = strlena(Languages); + for (Position=0; Position < Length; Position += ISO_639_2_ENTRY_SIZE) { + + // + // If this code matches, use this driver + // + + if (CompareMem (Languages+Position, LangCode, ISO_639_2_ENTRY_SIZE) == 0) { + UnicodeInterface = Ui; + goto Done; + } + } + } + +Done: + // + // Cleanup + // + + if (Handles) { + FreePool (Handles); + } +} + +VOID +EFIDebugVariable ( + VOID + ) +{ + EFI_STATUS Status; + UINT32 Attributes; + UINTN DataSize; + UINTN NewEFIDebug; + + DataSize = sizeof(EFIDebug); + Status = uefi_call_wrapper(RT->GetVariable, 5, L"EFIDebug", &EfiGlobalVariable, &Attributes, &DataSize, &NewEFIDebug); + if (!EFI_ERROR(Status)) { + EFIDebug = NewEFIDebug; + } +} + +/* + * Calls to memset/memcpy may be emitted implicitly by GCC or MSVC + * even when -ffreestanding or /NODEFAULTLIB are in effect. + */ + +#ifndef __SIZE_TYPE__ +#define __SIZE_TYPE__ UINTN +#endif + +void *memset(void *s, int c, __SIZE_TYPE__ n) +{ + unsigned char *p = s; + + while (n--) + *p++ = c; + + return s; +} + +void *memcpy(void *dest, const void *src, __SIZE_TYPE__ n) +{ + const unsigned char *q = src; + unsigned char *p = dest; + + while (n--) + *p++ = *q++; + + return dest; +} diff --git a/gnu-efi/lib/lib.h b/gnu-efi/lib/lib.h new file mode 100644 index 0000000..37fbb95 --- /dev/null +++ b/gnu-efi/lib/lib.h @@ -0,0 +1,92 @@ +/*++ + +Copyright (c) 1998 Intel Corporation + +Module Name: + + lib.h + +Abstract: + + EFI library header files + + + +Revision History + +--*/ + +#ifdef __GNUC__ +#pragma GCC visibility push(hidden) +#endif + +#include "efi.h" +#include "efilib.h" +#include "efirtlib.h" + +// +// Include non architectural protocols +// +#include "efivar.h" +#include "legacyboot.h" +#include "intload.h" +#include "vgaclass.h" +#include "eficonsplit.h" +#include "adapterdebug.h" +#include "intload.h" + +#include "efigpt.h" +#include "libsmbios.h" + +// +// Prototypes +// + +VOID +InitializeGuid ( + VOID + ); + +INTN EFIAPI +LibStubStriCmp ( + IN EFI_UNICODE_COLLATION_INTERFACE *This, + IN CHAR16 *S1, + IN CHAR16 *S2 + ); + +BOOLEAN EFIAPI +LibStubMetaiMatch ( + IN EFI_UNICODE_COLLATION_INTERFACE *This, + IN CHAR16 *String, + IN CHAR16 *Pattern + ); + +VOID EFIAPI +LibStubStrLwrUpr ( + IN EFI_UNICODE_COLLATION_INTERFACE *This, + IN CHAR16 *Str + ); + +BOOLEAN +LibMatchDevicePaths ( + IN EFI_DEVICE_PATH *Multi, + IN EFI_DEVICE_PATH *Single + ); + +EFI_DEVICE_PATH * +LibDuplicateDevicePathInstance ( + IN EFI_DEVICE_PATH *DevPath + ); + + +// +// Globals +// +extern BOOLEAN LibInitialized; +extern BOOLEAN LibFwInstance; +extern EFI_HANDLE LibImageHandle; +extern SIMPLE_TEXT_OUTPUT_INTERFACE *LibRuntimeDebugOut; +extern EFI_UNICODE_COLLATION_INTERFACE *UnicodeInterface; +extern EFI_UNICODE_COLLATION_INTERFACE LibStubUnicodeInterface; +extern EFI_RAISE_TPL LibRuntimeRaiseTPL; +extern EFI_RESTORE_TPL LibRuntimeRestoreTPL; diff --git a/gnu-efi/lib/lock.c b/gnu-efi/lib/lock.c new file mode 100644 index 0000000..a33bec3 --- /dev/null +++ b/gnu-efi/lib/lock.c @@ -0,0 +1,107 @@ +/*++ + +Copyright (c) 1998 Intel Corporation + +Module Name: + + lock.c + +Abstract: + + Implements FLOCK + + + +Revision History + +--*/ + + +#include "lib.h" + + +VOID +InitializeLock ( + IN OUT FLOCK *Lock, + IN EFI_TPL Priority + ) +/*++ + +Routine Description: + + Initialize a basic mutual exclusion lock. Each lock + provides mutual exclusion access at it's task priority + level. Since there is no-premption (at any TPL) or + multiprocessor support, acquiring the lock only consists + of raising to the locks TPL. + + Note on a debug build the lock is acquired and released + to help ensure proper usage. + +Arguments: + + Lock - The FLOCK structure to initialize + + Priority - The task priority level of the lock + + +Returns: + + An initialized F Lock structure. + +--*/ +{ + Lock->Tpl = Priority; + Lock->OwnerTpl = 0; + Lock->Lock = 0; +} + + +VOID +AcquireLock ( + IN FLOCK *Lock + ) +/*++ + +Routine Description: + + Raising to the task priority level of the mutual exclusion + lock, and then acquires ownership of the lock. + +Arguments: + + Lock - The lock to acquire + +Returns: + + Lock owned + +--*/ +{ + RtAcquireLock (Lock); +} + + +VOID +ReleaseLock ( + IN FLOCK *Lock + ) +/*++ + +Routine Description: + + Releases ownership of the mutual exclusion lock, and + restores the previous task priority level. + +Arguments: + + Lock - The lock to release + +Returns: + + Lock unowned + +--*/ +{ + RtReleaseLock (Lock); +} diff --git a/gnu-efi/lib/mips64el/efi_stub.S b/gnu-efi/lib/mips64el/efi_stub.S new file mode 100644 index 0000000..464eae5 --- /dev/null +++ b/gnu-efi/lib/mips64el/efi_stub.S @@ -0,0 +1 @@ +/* This stub is a stub to make the build happy */ diff --git a/gnu-efi/lib/mips64el/initplat.c b/gnu-efi/lib/mips64el/initplat.c new file mode 100644 index 0000000..6c5e1fa --- /dev/null +++ b/gnu-efi/lib/mips64el/initplat.c @@ -0,0 +1,26 @@ +/* + * Copright (C) 2014 Linaro Ltd. + * Author: Ard Biesheuvel + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice and this list of conditions, without modification. + * 2. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * Alternatively, this software may be distributed 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. + */ + +#include "lib.h" + +VOID +InitializeLibPlatform ( + IN EFI_HANDLE ImageHandle EFI_UNUSED, + IN EFI_SYSTEM_TABLE *SystemTable EFI_UNUSED + ) +{ +} diff --git a/gnu-efi/lib/mips64el/math.c b/gnu-efi/lib/mips64el/math.c new file mode 100644 index 0000000..8c16444 --- /dev/null +++ b/gnu-efi/lib/mips64el/math.c @@ -0,0 +1,63 @@ +/* + * Copright (C) 2014 Linaro Ltd. + * Author: Ard Biesheuvel + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice and this list of conditions, without modification. + * 2. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * Alternatively, this software may be distributed 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. + */ + +#include "lib.h" + +UINT64 +LShiftU64 ( + IN UINT64 Operand, + IN UINTN Count + ) +// Left shift 64bit by 32bit and get a 64bit result +{ + return Operand << Count; +} + +UINT64 +RShiftU64 ( + IN UINT64 Operand, + IN UINTN Count + ) +// Right shift 64bit by 32bit and get a 64bit result +{ + return Operand >> Count; +} + + +UINT64 +MultU64x32 ( + IN UINT64 Multiplicand, + IN UINTN Multiplier + ) +// Multiple 64bit by 32bit and get a 64bit result +{ + return Multiplicand * Multiplier; +} + +UINT64 +DivU64x32 ( + IN UINT64 Dividend, + IN UINTN Divisor, + OUT UINTN *Remainder OPTIONAL + ) +// divide 64bit by 32bit and get a 64bit result +// N.B. only works for 31bit divisors!! +{ + if (Remainder) + *Remainder = Dividend % Divisor; + return Dividend / Divisor; +} diff --git a/gnu-efi/lib/mips64el/setjmp.S b/gnu-efi/lib/mips64el/setjmp.S new file mode 100644 index 0000000..930aca4 --- /dev/null +++ b/gnu-efi/lib/mips64el/setjmp.S @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved. + * Copright (c) 2017 Lemote Co. + * Author: Heiher + * + * This program and the accompanying materials are licensed and made +available + * under the terms and conditions of the BSD License which accompanies +this + * distribution. The full text of the license may be found at + * http://opensource.org/licenses/bsd-license.php. + * + * THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" +BASIS, + * WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR + * IMPLIED. + */ + .text + .p2align 3 + + .globl setjmp + .type setjmp, @function +setjmp: + sd $ra, 0x00($a0) + sd $sp, 0x08($a0) + sd $fp, 0x10($a0) + sd $gp, 0x18($a0) + + sd $s0, 0x20($a0) + sd $s1, 0x28($a0) + sd $s2, 0x30($a0) + sd $s3, 0x38($a0) + sd $s4, 0x40($a0) + sd $s5, 0x48($a0) + sd $s6, 0x50($a0) + sd $s7, 0x58($a0) + +#ifdef __mips_hard_float + mfc0 $v0, $12 + ext $v0, $v0, 29, 1 + beqz $v0, 1f + + s.d $f24, 0x60($a0) + s.d $f25, 0x68($a0) + s.d $f26, 0x70($a0) + s.d $f27, 0x78($a0) + s.d $f28, 0x80($a0) + s.d $f29, 0x88($a0) + s.d $f30, 0x90($a0) + s.d $f31, 0x98($a0) + +1: +#endif + move $v0, $zero + jr $ra + + .globl longjmp + .type longjmp, @function +longjmp: + ld $ra, 0x00($a0) + ld $sp, 0x08($a0) + ld $fp, 0x10($a0) + ld $gp, 0x18($a0) + + ld $s0, 0x20($a0) + ld $s1, 0x28($a0) + ld $s2, 0x30($a0) + ld $s3, 0x38($a0) + ld $s4, 0x40($a0) + ld $s5, 0x48($a0) + ld $s6, 0x50($a0) + ld $s7, 0x58($a0) + +#ifdef __mips_hard_float + mfc0 $v0, $12 + ext $v0, $v0, 29, 1 + beqz $v0, 1f + + l.d $f24, 0x60($a0) + l.d $f25, 0x68($a0) + l.d $f26, 0x70($a0) + l.d $f27, 0x78($a0) + l.d $f28, 0x80($a0) + l.d $f29, 0x88($a0) + l.d $f30, 0x90($a0) + l.d $f31, 0x98($a0) + +1: +#endif + li $v0, 1 + movn $v0, $a1, $a1 + jr $ra diff --git a/gnu-efi/lib/misc.c b/gnu-efi/lib/misc.c new file mode 100644 index 0000000..fdcc934 --- /dev/null +++ b/gnu-efi/lib/misc.c @@ -0,0 +1,563 @@ +/*++ + +Copyright (c) 1998 Intel Corporation + +Module Name: + + misc.c + +Abstract: + + + + +Revision History + +--*/ + +#include "lib.h" + + +// +// +// + +VOID * +AllocatePool ( + IN UINTN Size + ) +{ + EFI_STATUS Status; + VOID *p; + + Status = uefi_call_wrapper(BS->AllocatePool, 3, PoolAllocationType, Size, &p); + if (EFI_ERROR(Status)) { + DEBUG((D_ERROR, "AllocatePool: out of pool %x\n", Status)); + p = NULL; + } + return p; +} + +VOID * +AllocateZeroPool ( + IN UINTN Size + ) +{ + VOID *p; + + p = AllocatePool (Size); + if (p) { + ZeroMem (p, Size); + } + + return p; +} + +VOID * +ReallocatePool ( + IN VOID *OldPool, + IN UINTN OldSize, + IN UINTN NewSize + ) +{ + VOID *NewPool; + + NewPool = NULL; + if (NewSize) { + NewPool = AllocatePool (NewSize); + } + + if (OldPool) { + if (NewPool) { + CopyMem (NewPool, OldPool, OldSize < NewSize ? OldSize : NewSize); + } + + FreePool (OldPool); + } + + return NewPool; +} + + +VOID +FreePool ( + IN VOID *Buffer + ) +{ + uefi_call_wrapper(BS->FreePool, 1, Buffer); +} + + + +VOID +ZeroMem ( + IN VOID *Buffer, + IN UINTN Size + ) +{ + RtZeroMem (Buffer, Size); +} + +VOID +SetMem ( + IN VOID *Buffer, + IN UINTN Size, + IN UINT8 Value + ) +{ + RtSetMem (Buffer, Size, Value); +} + +VOID +CopyMem ( + IN VOID *Dest, + IN CONST VOID *Src, + IN UINTN len + ) +{ + RtCopyMem (Dest, Src, len); +} + +INTN +CompareMem ( + IN CONST VOID *Dest, + IN CONST VOID *Src, + IN UINTN len + ) +{ + return RtCompareMem (Dest, Src, len); +} + +BOOLEAN +GrowBuffer( + IN OUT EFI_STATUS *Status, + IN OUT VOID **Buffer, + IN UINTN BufferSize + ) +/*++ + +Routine Description: + + Helper function called as part of the code needed + to allocate the proper sized buffer for various + EFI interfaces. + +Arguments: + + Status - Current status + + Buffer - Current allocated buffer, or NULL + + BufferSize - Current buffer size needed + +Returns: + + TRUE - if the buffer was reallocated and the caller + should try the API again. + +--*/ +{ + BOOLEAN TryAgain; + + // + // If this is an initial request, buffer will be null with a new buffer size + // + + if (!*Buffer && BufferSize) { + *Status = EFI_BUFFER_TOO_SMALL; + } + + // + // If the status code is "buffer too small", resize the buffer + // + + TryAgain = FALSE; + if (*Status == EFI_BUFFER_TOO_SMALL) { + + if (*Buffer) { + FreePool (*Buffer); + } + + *Buffer = AllocatePool (BufferSize); + + if (*Buffer) { + TryAgain = TRUE; + } else { + *Status = EFI_OUT_OF_RESOURCES; + } + } + + // + // If there's an error, free the buffer + // + + if (!TryAgain && EFI_ERROR(*Status) && *Buffer) { + FreePool (*Buffer); + *Buffer = NULL; + } + + return TryAgain; +} + + +EFI_MEMORY_DESCRIPTOR * +LibMemoryMap ( + OUT UINTN *NoEntries, + OUT UINTN *MapKey, + OUT UINTN *DescriptorSize, + OUT UINT32 *DescriptorVersion + ) +{ + EFI_STATUS Status; + EFI_MEMORY_DESCRIPTOR *Buffer; + UINTN BufferSize; + + // + // Initialize for GrowBuffer loop + // + + Status = EFI_SUCCESS; + Buffer = NULL; + BufferSize = sizeof(EFI_MEMORY_DESCRIPTOR); + + // + // Call the real function + // + + while (GrowBuffer (&Status, (VOID **) &Buffer, BufferSize)) { + Status = uefi_call_wrapper(BS->GetMemoryMap, 5, &BufferSize, Buffer, MapKey, DescriptorSize, DescriptorVersion); + } + + // + // Convert buffer size to NoEntries + // + + if (!EFI_ERROR(Status)) { + *NoEntries = BufferSize / *DescriptorSize; + } + + return Buffer; +} + +VOID * +LibGetVariableAndSize ( + IN CHAR16 *Name, + IN EFI_GUID *VendorGuid, + OUT UINTN *VarSize + ) +{ + EFI_STATUS Status; + VOID *Buffer; + UINTN BufferSize; + + // + // Initialize for GrowBuffer loop + // + + Buffer = NULL; + BufferSize = 100; + + // + // Call the real function + // + + while (GrowBuffer (&Status, &Buffer, BufferSize)) { + Status = uefi_call_wrapper( + RT->GetVariable, + 5, + Name, + VendorGuid, + NULL, + &BufferSize, + Buffer + ); + } + if (Buffer) { + *VarSize = BufferSize; + } else { + *VarSize = 0; + } + return Buffer; +} + +VOID * +LibGetVariable ( + IN CHAR16 *Name, + IN EFI_GUID *VendorGuid + ) +{ + UINTN VarSize; + + return LibGetVariableAndSize (Name, VendorGuid, &VarSize); +} + +EFI_STATUS +LibDeleteVariable ( + IN CHAR16 *VarName, + IN EFI_GUID *VarGuid + ) +{ + VOID *VarBuf; + EFI_STATUS Status; + + VarBuf = LibGetVariable(VarName,VarGuid); + + Status = EFI_NOT_FOUND; + + if (VarBuf) { + // + // Delete variable from Storage + // + Status = uefi_call_wrapper( + RT->SetVariable, + 5, + VarName, VarGuid, + EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE, + 0, NULL + ); + ASSERT (!EFI_ERROR(Status)); + FreePool(VarBuf); + } + + return (Status); +} + +EFI_STATUS +LibSetNVVariable ( + IN CHAR16 *VarName, + IN EFI_GUID *VarGuid, + IN UINTN DataSize, + IN VOID *Data + ) +{ + EFI_STATUS Status; + + Status = uefi_call_wrapper( + RT->SetVariable, + 5, + VarName, VarGuid, + EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE, + DataSize, Data + ); + ASSERT (!EFI_ERROR(Status)); + return (Status); +} + +EFI_STATUS +LibSetVariable ( + IN CHAR16 *VarName, + IN EFI_GUID *VarGuid, + IN UINTN DataSize, + IN VOID *Data + ) +{ + EFI_STATUS Status; + + Status = uefi_call_wrapper( + RT->SetVariable, + 5, + VarName, VarGuid, + EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, + DataSize, Data + ); + ASSERT (!EFI_ERROR(Status)); + return (Status); +} + +EFI_STATUS +LibInsertToTailOfBootOrder ( + IN UINT16 BootOption, + IN BOOLEAN OnlyInsertIfEmpty + ) +{ + UINT16 *BootOptionArray; + UINT16 *NewBootOptionArray; + UINTN VarSize; + UINTN Index; + EFI_STATUS Status; + + BootOptionArray = LibGetVariableAndSize (VarBootOrder, &EfiGlobalVariable, &VarSize); + if (VarSize != 0 && OnlyInsertIfEmpty) { + if (BootOptionArray) { + FreePool (BootOptionArray); + } + return EFI_UNSUPPORTED; + } + + VarSize += sizeof(UINT16); + NewBootOptionArray = AllocatePool (VarSize); + + for (Index = 0; Index < ((VarSize/sizeof(UINT16)) - 1); Index++) { + NewBootOptionArray[Index] = BootOptionArray[Index]; + } + // + // Insert in the tail of the array + // + NewBootOptionArray[Index] = BootOption; + + Status = uefi_call_wrapper( + RT->SetVariable, + 5, + VarBootOrder, &EfiGlobalVariable, + EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE, + VarSize, (VOID*) NewBootOptionArray + ); + + if (NewBootOptionArray) { + FreePool (NewBootOptionArray); + } + if (BootOptionArray) { + FreePool (BootOptionArray); + } + return Status; +} + + +BOOLEAN +ValidMBR( + IN MASTER_BOOT_RECORD *Mbr, + IN EFI_BLOCK_IO *BlkIo + ) +{ + UINT32 StartingLBA, EndingLBA; + UINT32 NewEndingLBA; + INTN i, j; + BOOLEAN ValidMbr; + + if (Mbr->Signature != MBR_SIGNATURE) { + // + // The BPB also has this signature, so it can not be used alone. + // + return FALSE; + } + + ValidMbr = FALSE; + for (i=0; iPartition[i].OSIndicator == 0x00 || EXTRACT_UINT32(Mbr->Partition[i].SizeInLBA) == 0 ) { + continue; + } + ValidMbr = TRUE; + StartingLBA = EXTRACT_UINT32(Mbr->Partition[i].StartingLBA); + EndingLBA = StartingLBA + EXTRACT_UINT32(Mbr->Partition[i].SizeInLBA) - 1; + if (EndingLBA > BlkIo->Media->LastBlock) { + // + // Compatability Errata: + // Some systems try to hide drive space with thier INT 13h driver + // This does not hide space from the OS driver. This means the MBR + // that gets created from DOS is smaller than the MBR created from + // a real OS (NT & Win98). This leads to BlkIo->LastBlock being + // wrong on some systems FDISKed by the OS. + // + // + if (BlkIo->Media->LastBlock < MIN_MBR_DEVICE_SIZE) { + // + // If this is a very small device then trust the BlkIo->LastBlock + // + return FALSE; + } + + if (EndingLBA > (BlkIo->Media->LastBlock + MBR_ERRATA_PAD)) { + return FALSE; + } + + } + for (j=i+1; jPartition[j].OSIndicator == 0x00 || EXTRACT_UINT32(Mbr->Partition[j].SizeInLBA) == 0) { + continue; + } + if ( EXTRACT_UINT32(Mbr->Partition[j].StartingLBA) >= StartingLBA && + EXTRACT_UINT32(Mbr->Partition[j].StartingLBA) <= EndingLBA ) { + // + // The Start of this region overlaps with the i'th region + // + return FALSE; + } + NewEndingLBA = EXTRACT_UINT32(Mbr->Partition[j].StartingLBA) + EXTRACT_UINT32(Mbr->Partition[j].SizeInLBA) - 1; + if ( NewEndingLBA >= StartingLBA && NewEndingLBA <= EndingLBA ) { + // + // The End of this region overlaps with the i'th region + // + return FALSE; + } + } + } + // + // Non of the regions overlapped so MBR is O.K. + // + return ValidMbr; +} + + +UINT8 +DecimaltoBCD( + IN UINT8 DecValue + ) +{ + return RtDecimaltoBCD (DecValue); +} + + +UINT8 +BCDtoDecimal( + IN UINT8 BcdValue + ) +{ + return RtBCDtoDecimal (BcdValue); +} + +EFI_STATUS +LibGetSystemConfigurationTable( + IN EFI_GUID *TableGuid, + IN OUT VOID **Table + ) + +{ + UINTN Index; + + for(Index=0;IndexNumberOfTableEntries;Index++) { + if (CompareGuid(TableGuid,&(ST->ConfigurationTable[Index].VendorGuid))==0) { + *Table = ST->ConfigurationTable[Index].VendorTable; + return EFI_SUCCESS; + } + } + return EFI_NOT_FOUND; +} + + +CHAR16 * +LibGetUiString ( + IN EFI_HANDLE Handle, + IN UI_STRING_TYPE StringType, + IN ISO_639_2 *LangCode, + IN BOOLEAN ReturnDevicePathStrOnMismatch + ) +{ + UI_INTERFACE *Ui; + UI_STRING_TYPE Index; + UI_STRING_ENTRY *Array; + EFI_STATUS Status; + + Status = uefi_call_wrapper(BS->HandleProtocol, 3, Handle, &UiProtocol, (VOID *)&Ui); + if (EFI_ERROR(Status)) { + return (ReturnDevicePathStrOnMismatch) ? DevicePathToStr(DevicePathFromHandle(Handle)) : NULL; + } + + // + // Skip the first strings + // + for (Index = UiDeviceString, Array = Ui->Entry; Index < StringType; Index++, Array++) { + while (Array->LangCode) { + Array++; + } + } + + // + // Search for the match + // + while (Array->LangCode) { + if (strcmpa (Array->LangCode, LangCode) == 0) { + return Array->UiString; + } + } + return (ReturnDevicePathStrOnMismatch) ? DevicePathToStr(DevicePathFromHandle(Handle)) : NULL; +} diff --git a/gnu-efi/lib/print.c b/gnu-efi/lib/print.c new file mode 100644 index 0000000..35e43c0 --- /dev/null +++ b/gnu-efi/lib/print.c @@ -0,0 +1,1482 @@ +/*++ + +Copyright (c) 1998 Intel Corporation + +Module Name: + + print.c + +Abstract: + + + + +Revision History + +--*/ + +#include "lib.h" +#include "efistdarg.h" // !!! + +// +// Declare runtime functions +// + +#ifdef RUNTIME_CODE +#ifndef __GNUC__ +#pragma RUNTIME_CODE(DbgPrint) + +// For debugging.. + +/* +#pragma RUNTIME_CODE(_Print) +#pragma RUNTIME_CODE(PFLUSH) +#pragma RUNTIME_CODE(PSETATTR) +#pragma RUNTIME_CODE(PPUTC) +#pragma RUNTIME_CODE(PGETC) +#pragma RUNTIME_CODE(PITEM) +#pragma RUNTIME_CODE(ValueToHex) +#pragma RUNTIME_CODE(ValueToString) +#pragma RUNTIME_CODE(TimeToString) +*/ + +#endif /* !defined(__GNUC__) */ +#endif + +// +// +// + + +#define PRINT_STRING_LEN 200 +#define PRINT_ITEM_BUFFER_LEN 100 + +typedef struct { + BOOLEAN Ascii; + UINTN Index; + union { + CONST CHAR16 *pw; + CONST CHAR8 *pc; + } un; +} POINTER; + +#define pw un.pw +#define pc un.pc + +typedef struct _pitem { + + POINTER Item; + CHAR16 Scratch[PRINT_ITEM_BUFFER_LEN]; + UINTN Width; + UINTN FieldWidth; + UINTN *WidthParse; + CHAR16 Pad; + BOOLEAN PadBefore; + BOOLEAN Comma; + BOOLEAN Long; +} PRINT_ITEM; + + +typedef struct _pstate { + // Input + POINTER fmt; + va_list args; + + // Output + CHAR16 *Buffer; + CHAR16 *End; + CHAR16 *Pos; + UINTN Len; + + UINTN Attr; + UINTN RestoreAttr; + + UINTN AttrNorm; + UINTN AttrHighlight; + UINTN AttrError; + + INTN (EFIAPI *Output)(VOID *context, CHAR16 *str); + INTN (EFIAPI *SetAttr)(VOID *context, UINTN attr); + VOID *Context; + + // Current item being formatted + struct _pitem *Item; +} PRINT_STATE; + +// +// Internal fucntions +// + +STATIC +UINTN +_Print ( + IN PRINT_STATE *ps + ); + +STATIC +UINTN +_IPrint ( + IN UINTN Column, + IN UINTN Row, + IN SIMPLE_TEXT_OUTPUT_INTERFACE *Out, + IN CONST CHAR16 *fmt, + IN CONST CHAR8 *fmta, + IN va_list args + ); + +STATIC +INTN EFIAPI +_DbgOut ( + IN VOID *Context, + IN CHAR16 *Buffer + ); + +STATIC +VOID +PFLUSH ( + IN OUT PRINT_STATE *ps + ); + +STATIC +VOID +PPUTC ( + IN OUT PRINT_STATE *ps, + IN CHAR16 c + ); + +STATIC +VOID +PITEM ( + IN OUT PRINT_STATE *ps + ); + +STATIC +CHAR16 +PGETC ( + IN POINTER *p + ); + +STATIC +VOID +PSETATTR ( + IN OUT PRINT_STATE *ps, + IN UINTN Attr + ); + +// +// +// + +INTN EFIAPI +_SPrint ( + IN VOID *Context, + IN CHAR16 *Buffer + ); + +INTN EFIAPI +_PoolPrint ( + IN VOID *Context, + IN CHAR16 *Buffer + ); + +INTN +DbgPrint ( + IN INTN mask, + IN CONST CHAR8 *fmt, + ... + ) +/*++ + +Routine Description: + + Prints a formatted unicode string to the default StandardError console + +Arguments: + + mask - Bit mask of debug string. If a bit is set in the + mask that is also set in EFIDebug the string is + printed; otherwise, the string is not printed + + fmt - Format string + +Returns: + + Length of string printed to the StandardError console + +--*/ +{ + SIMPLE_TEXT_OUTPUT_INTERFACE *DbgOut; + PRINT_STATE ps; + va_list args; + UINTN back; + UINTN attr; + UINTN SavedAttribute; + + + if (!(EFIDebug & mask)) { + return 0; + } + + va_start (args, fmt); + ZeroMem (&ps, sizeof(ps)); + + ps.Output = _DbgOut; + ps.fmt.Ascii = TRUE; + ps.fmt.pc = fmt; + va_copy(ps.args, args); + ps.Attr = EFI_TEXT_ATTR(EFI_LIGHTGRAY, EFI_RED); + + DbgOut = LibRuntimeDebugOut; + + if (!DbgOut) { + DbgOut = ST->StdErr; + } + + if (DbgOut) { + ps.Attr = DbgOut->Mode->Attribute; + ps.Context = DbgOut; + ps.SetAttr = (INTN (EFIAPI *)(VOID *, UINTN)) DbgOut->SetAttribute; + } + + SavedAttribute = ps.Attr; + + back = (ps.Attr >> 4) & 0xf; + ps.AttrNorm = EFI_TEXT_ATTR(EFI_LIGHTGRAY, back); + ps.AttrHighlight = EFI_TEXT_ATTR(EFI_WHITE, back); + ps.AttrError = EFI_TEXT_ATTR(EFI_YELLOW, back); + + attr = ps.AttrNorm; + + if (mask & D_WARN) { + attr = ps.AttrHighlight; + } + + if (mask & D_ERROR) { + attr = ps.AttrError; + } + + if (ps.SetAttr) { + ps.Attr = attr; + uefi_call_wrapper(ps.SetAttr, 2, ps.Context, attr); + } + + _Print (&ps); + + va_end (ps.args); + va_end (args); + + // + // Restore original attributes + // + + if (ps.SetAttr) { + uefi_call_wrapper(ps.SetAttr, 2, ps.Context, SavedAttribute); + } + + return 0; +} + +STATIC +INTN +IsLocalPrint(void *func) +{ + if (func == _DbgOut || func == _SPrint || func == _PoolPrint) + return 1; + return 0; +} + +STATIC +INTN EFIAPI +_DbgOut ( + IN VOID *Context, + IN CHAR16 *Buffer + ) +// Append string worker for DbgPrint +{ + SIMPLE_TEXT_OUTPUT_INTERFACE *DbgOut; + + DbgOut = Context; +// if (!DbgOut && ST && ST->ConOut) { +// DbgOut = ST->ConOut; +// } + + if (DbgOut) { + if (IsLocalPrint(DbgOut->OutputString)) + DbgOut->OutputString(DbgOut, Buffer); + else + uefi_call_wrapper(DbgOut->OutputString, 2, DbgOut, Buffer); + } + + return 0; +} + +INTN EFIAPI +_SPrint ( + IN VOID *Context, + IN CHAR16 *Buffer + ) +// Append string worker for SPrint, PoolPrint and CatPrint +{ + UINTN len; + POOL_PRINT *spc; + + spc = Context; + len = StrLen(Buffer); + + // + // Is the string is over the max truncate it + // + + if (spc->len + len > spc->maxlen) { + len = spc->maxlen - spc->len; + } + + // + // Append the new text + // + + CopyMem (spc->str + spc->len, Buffer, len * sizeof(CHAR16)); + spc->len += len; + + // + // Null terminate it + // + + if (spc->len < spc->maxlen) { + spc->str[spc->len] = 0; + } else if (spc->maxlen) { + spc->str[spc->maxlen] = 0; + } + + return 0; +} + + +INTN EFIAPI +_PoolPrint ( + IN VOID *Context, + IN CHAR16 *Buffer + ) +// Append string worker for PoolPrint and CatPrint +{ + UINTN newlen; + POOL_PRINT *spc; + + spc = Context; + newlen = spc->len + StrLen(Buffer) + 1; + + // + // Is the string is over the max, grow the buffer + // + + if (newlen > spc->maxlen) { + + // + // Grow the pool buffer + // + + newlen += PRINT_STRING_LEN; + spc->maxlen = newlen; + spc->str = ReallocatePool ( + spc->str, + spc->len * sizeof(CHAR16), + spc->maxlen * sizeof(CHAR16) + ); + + if (!spc->str) { + spc->len = 0; + spc->maxlen = 0; + } + } + + // + // Append the new text + // + + return _SPrint (Context, Buffer); +} + + + +VOID +_PoolCatPrint ( + IN CONST CHAR16 *fmt, + IN va_list args, + IN OUT POOL_PRINT *spc, + IN INTN (EFIAPI *Output)(VOID *context, CHAR16 *str) + ) +// Dispath function for SPrint, PoolPrint, and CatPrint +{ + PRINT_STATE ps; + + ZeroMem (&ps, sizeof(ps)); + ps.Output = Output; + ps.Context = spc; + ps.fmt.pw = fmt; + va_copy(ps.args, args); + _Print (&ps); + va_end(ps.args); +} + + + +UINTN +VSPrint ( + OUT CHAR16 *Str, + IN UINTN StrSize, + IN CONST CHAR16 *fmt, + va_list args + ) +/*++ + +Routine Description: + + Prints a formatted unicode string to a buffer using a va_list + +Arguments: + + Str - Output buffer to print the formatted string into + + StrSize - Size of Str. String is truncated to this size. + A size of 0 means there is no limit + + fmt - The format string + + args - va_list + + +Returns: + + String length returned in buffer + +--*/ +{ + POOL_PRINT spc; + + spc.str = Str; + spc.maxlen = StrSize / sizeof(CHAR16) - 1; + spc.len = 0; + + _PoolCatPrint (fmt, args, &spc, _SPrint); + + return spc.len; +} + +UINTN +SPrint ( + OUT CHAR16 *Str, + IN UINTN StrSize, + IN CONST CHAR16 *fmt, + ... + ) +/*++ + +Routine Description: + + Prints a formatted unicode string to a buffer + +Arguments: + + Str - Output buffer to print the formatted string into + + StrSize - Size of Str. String is truncated to this size. + A size of 0 means there is no limit + + fmt - The format string + +Returns: + + String length returned in buffer + +--*/ +{ + va_list args; + UINTN len; + + va_start (args, fmt); + len = VSPrint(Str, StrSize, fmt, args); + va_end (args); + + return len; +} + +CHAR16 * +VPoolPrint ( + IN CONST CHAR16 *fmt, + va_list args + ) +/*++ + +Routine Description: + + Prints a formatted unicode string to allocated pool using va_list argument. + The caller must free the resulting buffer. + +Arguments: + + fmt - The format string + args - The arguments in va_list form + +Returns: + + Allocated buffer with the formatted string printed in it. + The caller must free the allocated buffer. The buffer + allocation is not packed. + +--*/ +{ + POOL_PRINT spc; + ZeroMem (&spc, sizeof(spc)); + _PoolCatPrint (fmt, args, &spc, _PoolPrint); + return spc.str; +} + +CHAR16 * +PoolPrint ( + IN CONST CHAR16 *fmt, + ... + ) +/*++ + +Routine Description: + + Prints a formatted unicode string to allocated pool. The caller + must free the resulting buffer. + +Arguments: + + fmt - The format string + +Returns: + + Allocated buffer with the formatted string printed in it. + The caller must free the allocated buffer. The buffer + allocation is not packed. + +--*/ +{ + va_list args; + CHAR16 *pool; + va_start (args, fmt); + pool = VPoolPrint(fmt, args); + va_end (args); + return pool; +} + +CHAR16 * +CatPrint ( + IN OUT POOL_PRINT *Str, + IN CONST CHAR16 *fmt, + ... + ) +/*++ + +Routine Description: + + Concatenates a formatted unicode string to allocated pool. + The caller must free the resulting buffer. + +Arguments: + + Str - Tracks the allocated pool, size in use, and + amount of pool allocated. + + fmt - The format string + +Returns: + + Allocated buffer with the formatted string printed in it. + The caller must free the allocated buffer. The buffer + allocation is not packed. + +--*/ +{ + va_list args; + + va_start (args, fmt); + _PoolCatPrint (fmt, args, Str, _PoolPrint); + va_end (args); + return Str->str; +} + + + +UINTN +Print ( + IN CONST CHAR16 *fmt, + ... + ) +/*++ + +Routine Description: + + Prints a formatted unicode string to the default console + +Arguments: + + fmt - Format string + +Returns: + + Length of string printed to the console + +--*/ +{ + va_list args; + UINTN back; + + va_start (args, fmt); + back = _IPrint ((UINTN) -1, (UINTN) -1, ST->ConOut, fmt, NULL, args); + va_end (args); + return back; +} + +UINTN +VPrint ( + IN CONST CHAR16 *fmt, + va_list args + ) +/*++ + +Routine Description: + + Prints a formatted unicode string to the default console using a va_list + +Arguments: + + fmt - Format string + args - va_list +Returns: + + Length of string printed to the console + +--*/ +{ + return _IPrint ((UINTN) -1, (UINTN) -1, ST->ConOut, fmt, NULL, args); +} + + +UINTN +PrintAt ( + IN UINTN Column, + IN UINTN Row, + IN CONST CHAR16 *fmt, + ... + ) +/*++ + +Routine Description: + + Prints a formatted unicode string to the default console, at + the supplied cursor position + +Arguments: + + Column, Row - The cursor position to print the string at + + fmt - Format string + +Returns: + + Length of string printed to the console + +--*/ +{ + va_list args; + UINTN back; + + va_start (args, fmt); + back = _IPrint (Column, Row, ST->ConOut, fmt, NULL, args); + va_end (args); + return back; +} + + +UINTN +IPrint ( + IN SIMPLE_TEXT_OUTPUT_INTERFACE *Out, + IN CONST CHAR16 *fmt, + ... + ) +/*++ + +Routine Description: + + Prints a formatted unicode string to the specified console + +Arguments: + + Out - The console to print the string too + + fmt - Format string + +Returns: + + Length of string printed to the console + +--*/ +{ + va_list args; + UINTN back; + + va_start (args, fmt); + back = _IPrint ((UINTN) -1, (UINTN) -1, Out, fmt, NULL, args); + va_end (args); + return back; +} + + +UINTN +IPrintAt ( + IN SIMPLE_TEXT_OUTPUT_INTERFACE *Out, + IN UINTN Column, + IN UINTN Row, + IN CONST CHAR16 *fmt, + ... + ) +/*++ + +Routine Description: + + Prints a formatted unicode string to the specified console, at + the supplied cursor position + +Arguments: + + Out - The console to print the string to + + Column, Row - The cursor position to print the string at + + fmt - Format string + +Returns: + + Length of string printed to the console + +--*/ +{ + va_list args; + UINTN back; + + va_start (args, fmt); + back = _IPrint (Column, Row, Out, fmt, NULL, args); + va_end (args); + return back; +} + + +UINTN +_IPrint ( + IN UINTN Column, + IN UINTN Row, + IN SIMPLE_TEXT_OUTPUT_INTERFACE *Out, + IN CONST CHAR16 *fmt, + IN CONST CHAR8 *fmta, + IN va_list args + ) +// Display string worker for: Print, PrintAt, IPrint, IPrintAt +{ + PRINT_STATE ps; + UINTN back; + + ZeroMem (&ps, sizeof(ps)); + ps.Context = Out; + ps.Output = (INTN (EFIAPI *)(VOID *, CHAR16 *)) Out->OutputString; + ps.SetAttr = (INTN (EFIAPI *)(VOID *, UINTN)) Out->SetAttribute; + ps.Attr = Out->Mode->Attribute; + + back = (ps.Attr >> 4) & 0xF; + ps.AttrNorm = EFI_TEXT_ATTR(EFI_LIGHTGRAY, back); + ps.AttrHighlight = EFI_TEXT_ATTR(EFI_WHITE, back); + ps.AttrError = EFI_TEXT_ATTR(EFI_YELLOW, back); + + if (fmt) { + ps.fmt.pw = fmt; + } else { + ps.fmt.Ascii = TRUE; + ps.fmt.pc = fmta; + } + + va_copy(ps.args, args); + + if (Column != (UINTN) -1) { + uefi_call_wrapper(Out->SetCursorPosition, 3, Out, Column, Row); + } + + back = _Print (&ps); + va_end(ps.args); + return back; +} + + +UINTN +APrint ( + IN CONST CHAR8 *fmt, + ... + ) +/*++ + +Routine Description: + + For those whom really can't deal with unicode, a print + function that takes an ascii format string + +Arguments: + + fmt - ascii format string + +Returns: + + Length of string printed to the console + +--*/ + +{ + va_list args; + UINTN back; + + va_start (args, fmt); + back = _IPrint ((UINTN) -1, (UINTN) -1, ST->ConOut, NULL, fmt, args); + va_end (args); + return back; +} + + +STATIC +VOID +PFLUSH ( + IN OUT PRINT_STATE *ps + ) +{ + *ps->Pos = 0; + if (IsLocalPrint(ps->Output)) + ps->Output(ps->Context, ps->Buffer); + else + uefi_call_wrapper(ps->Output, 2, ps->Context, ps->Buffer); + ps->Pos = ps->Buffer; +} + +STATIC +VOID +PSETATTR ( + IN OUT PRINT_STATE *ps, + IN UINTN Attr + ) +{ + PFLUSH (ps); + + ps->RestoreAttr = ps->Attr; + if (ps->SetAttr) { + uefi_call_wrapper(ps->SetAttr, 2, ps->Context, Attr); + } + + ps->Attr = Attr; +} + +STATIC +VOID +PPUTC ( + IN OUT PRINT_STATE *ps, + IN CHAR16 c + ) +{ + // if this is a newline, add a carraige return + if (c == '\n') { + PPUTC (ps, '\r'); + } + + *ps->Pos = c; + ps->Pos += 1; + ps->Len += 1; + + // if at the end of the buffer, flush it + if (ps->Pos >= ps->End) { + PFLUSH(ps); + } +} + + +STATIC +CHAR16 +PGETC ( + IN POINTER *p + ) +{ + CHAR16 c; + + c = p->Ascii ? p->pc[p->Index] : p->pw[p->Index]; + p->Index += 1; + + return c; +} + + +STATIC +VOID +PITEM ( + IN OUT PRINT_STATE *ps + ) +{ + UINTN Len, i; + PRINT_ITEM *Item; + CHAR16 c; + + // Get the length of the item + Item = ps->Item; + Item->Item.Index = 0; + while (Item->Item.Index < Item->FieldWidth) { + c = PGETC(&Item->Item); + if (!c) { + Item->Item.Index -= 1; + break; + } + } + Len = Item->Item.Index; + + // if there is no item field width, use the items width + if (Item->FieldWidth == (UINTN) -1) { + Item->FieldWidth = Len; + } + + // if item is larger then width, update width + if (Len > Item->Width) { + Item->Width = Len; + } + + + // if pad field before, add pad char + if (Item->PadBefore) { + for (i=Item->Width; i < Item->FieldWidth; i+=1) { + PPUTC (ps, ' '); + } + } + + // pad item + for (i=Len; i < Item->Width; i++) { + PPUTC (ps, Item->Pad); + } + + // add the item + Item->Item.Index=0; + while (Item->Item.Index < Len) { + PPUTC (ps, PGETC(&Item->Item)); + } + + // If pad at the end, add pad char + if (!Item->PadBefore) { + for (i=Item->Width; i < Item->FieldWidth; i+=1) { + PPUTC (ps, ' '); + } + } +} + + +STATIC +UINTN +_Print ( + IN PRINT_STATE *ps + ) +/*++ + +Routine Description: + + %w.lF - w = width + l = field width + F = format of arg + + Args F: + 0 - pad with zeros + - - justify on left (default is on right) + , - add comma's to field + * - width provided on stack + n - Set output attribute to normal (for this field only) + h - Set output attribute to highlight (for this field only) + e - Set output attribute to error (for this field only) + l - Value is 64 bits + + a - ascii string + s - unicode string + X - fixed 8 byte value in hex + x - hex value + d - value as signed decimal + u - value as unsigned decimal + f - value as floating point + c - Unicode char + t - EFI time structure + g - Pointer to GUID + r - EFI status code (result code) + D - pointer to Device Path with normal ending. + + N - Set output attribute to normal + H - Set output attribute to highlight + E - Set output attribute to error + % - Print a % + +Arguments: + + SystemTable - The system table + +Returns: + + Number of charactors written + +--*/ +{ + CHAR16 c; + UINTN Attr; + PRINT_ITEM Item; + CHAR16 Buffer[PRINT_STRING_LEN]; + + ps->Len = 0; + ps->Buffer = Buffer; + ps->Pos = Buffer; + ps->End = Buffer + PRINT_STRING_LEN - 1; + ps->Item = &Item; + + ps->fmt.Index = 0; + while ((c = PGETC(&ps->fmt))) { + + if (c != '%') { + PPUTC ( ps, c ); + continue; + } + + // setup for new item + Item.FieldWidth = (UINTN) -1; + Item.Width = 0; + Item.WidthParse = &Item.Width; + Item.Pad = ' '; + Item.PadBefore = TRUE; + Item.Comma = FALSE; + Item.Long = FALSE; + Item.Item.Ascii = FALSE; + Item.Item.pw = NULL; + ps->RestoreAttr = 0; + Attr = 0; + + while ((c = PGETC(&ps->fmt))) { + + switch (c) { + + case '%': + // + // %% -> % + // + Item.Scratch[0] = '%'; + Item.Scratch[1] = 0; + Item.Item.pw = Item.Scratch; + break; + + case '0': + Item.Pad = '0'; + break; + + case '-': + Item.PadBefore = FALSE; + break; + + case ',': + Item.Comma = TRUE; + break; + + case '.': + Item.WidthParse = &Item.FieldWidth; + break; + + case '*': + *Item.WidthParse = va_arg(ps->args, UINTN); + break; + + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + *Item.WidthParse = 0; + do { + *Item.WidthParse = *Item.WidthParse * 10 + c - '0'; + c = PGETC(&ps->fmt); + } while (c >= '0' && c <= '9') ; + ps->fmt.Index -= 1; + break; + + case 'a': + Item.Item.pc = va_arg(ps->args, CHAR8 *); + Item.Item.Ascii = TRUE; + if (!Item.Item.pc) { + Item.Item.pc = (CHAR8 *)"(null)"; + } + break; + + case 's': + Item.Item.pw = va_arg(ps->args, CHAR16 *); + if (!Item.Item.pw) { + Item.Item.pw = L"(null)"; + } + break; + + case 'c': + Item.Scratch[0] = (CHAR16) va_arg(ps->args, UINTN); + Item.Scratch[1] = 0; + Item.Item.pw = Item.Scratch; + break; + + case 'l': + Item.Long = TRUE; + break; + + case 'X': + Item.Width = Item.Long ? 16 : 8; + Item.Pad = '0'; +#if __GNUC__ >= 7 + __attribute__ ((fallthrough)); +#endif + case 'x': + ValueToHex ( + Item.Scratch, + Item.Long ? va_arg(ps->args, UINT64) : va_arg(ps->args, UINT32) + ); + Item.Item.pw = Item.Scratch; + + break; + + + case 'g': + GuidToString (Item.Scratch, va_arg(ps->args, EFI_GUID *)); + Item.Item.pw = Item.Scratch; + break; + + case 'u': + ValueToString ( + Item.Scratch, + Item.Comma, + Item.Long ? va_arg(ps->args, UINT64) : va_arg(ps->args, UINT32) + ); + Item.Item.pw = Item.Scratch; + break; + + case 'd': + ValueToString ( + Item.Scratch, + Item.Comma, + Item.Long ? va_arg(ps->args, INT64) : va_arg(ps->args, INT32) + ); + Item.Item.pw = Item.Scratch; + break; + + case 'D': + { + EFI_DEVICE_PATH *dp = va_arg(ps->args, EFI_DEVICE_PATH *); + CHAR16 *dpstr = DevicePathToStr(dp); + StrnCpy(Item.Scratch, dpstr, PRINT_ITEM_BUFFER_LEN); + Item.Scratch[PRINT_ITEM_BUFFER_LEN-1] = L'\0'; + FreePool(dpstr); + + Item.Item.pw = Item.Scratch; + break; + } + + case 'f': + FloatToString ( + Item.Scratch, + Item.Comma, + va_arg(ps->args, double) + ); + Item.Item.pw = Item.Scratch; + break; + + case 't': + TimeToString (Item.Scratch, va_arg(ps->args, EFI_TIME *)); + Item.Item.pw = Item.Scratch; + break; + + case 'r': + StatusToString (Item.Scratch, va_arg(ps->args, EFI_STATUS)); + Item.Item.pw = Item.Scratch; + break; + + case 'n': + PSETATTR(ps, ps->AttrNorm); + break; + + case 'h': + PSETATTR(ps, ps->AttrHighlight); + break; + + case 'e': + PSETATTR(ps, ps->AttrError); + break; + + case 'N': + Attr = ps->AttrNorm; + break; + + case 'H': + Attr = ps->AttrHighlight; + break; + + case 'E': + Attr = ps->AttrError; + break; + + default: + Item.Scratch[0] = '?'; + Item.Scratch[1] = 0; + Item.Item.pw = Item.Scratch; + break; + } + + // if we have an Item + if (Item.Item.pw) { + PITEM (ps); + break; + } + + // if we have an Attr set + if (Attr) { + PSETATTR(ps, Attr); + ps->RestoreAttr = 0; + break; + } + } + + if (ps->RestoreAttr) { + PSETATTR(ps, ps->RestoreAttr); + } + } + + // Flush buffer + PFLUSH (ps); + return ps->Len; +} + +STATIC CHAR8 Hex[] = {'0','1','2','3','4','5','6','7', + '8','9','A','B','C','D','E','F'}; + +VOID +ValueToHex ( + IN CHAR16 *Buffer, + IN UINT64 v + ) +{ + CHAR8 str[30], *p1; + CHAR16 *p2; + + if (!v) { + Buffer[0] = '0'; + Buffer[1] = 0; + return ; + } + + p1 = str; + p2 = Buffer; + + while (v) { + // Without the cast, the MSVC compiler may insert a reference to __allmull + *(p1++) = Hex[(UINTN)(v & 0xf)]; + v = RShiftU64 (v, 4); + } + + while (p1 != str) { + *(p2++) = *(--p1); + } + *p2 = 0; +} + + +VOID +ValueToString ( + IN CHAR16 *Buffer, + IN BOOLEAN Comma, + IN INT64 v + ) +{ + STATIC CHAR8 ca[] = { 3, 1, 2 }; + CHAR8 str[40], *p1; + CHAR16 *p2; + UINTN c, r; + + if (!v) { + Buffer[0] = '0'; + Buffer[1] = 0; + return ; + } + + p1 = str; + p2 = Buffer; + + if (v < 0) { + *(p2++) = '-'; + v = -v; + } + + while (v) { + v = (INT64)DivU64x32 ((UINT64)v, 10, &r); + *(p1++) = (CHAR8)r + '0'; + } + + c = (Comma ? ca[(p1 - str) % 3] : 999) + 1; + while (p1 != str) { + + c -= 1; + if (!c) { + *(p2++) = ','; + c = 3; + } + + *(p2++) = *(--p1); + } + *p2 = 0; +} + +VOID +FloatToString ( + IN CHAR16 *Buffer, + IN BOOLEAN Comma, + IN double v + ) +{ + /* + * Integer part. + */ + INTN i = (INTN)v; + ValueToString(Buffer, Comma, i); + + + /* + * Decimal point. + */ + UINTN x = StrLen(Buffer); + Buffer[x] = L'.'; + x++; + + + /* + * Keep fractional part. + */ + float f = (float)(v - i); + if (f < 0) f = -f; + + + /* + * Leading fractional zeroes. + */ + f *= 10.0; + while ( (f != 0) + && ((INTN)f == 0)) + { + Buffer[x] = L'0'; + x++; + f *= 10.0; + } + + + /* + * Fractional digits. + */ + while ((float)(INTN)f != f) + { + f *= 10; + } + ValueToString(Buffer + x, FALSE, (INTN)f); + return; +} + +VOID +TimeToString ( + OUT CHAR16 *Buffer, + IN EFI_TIME *Time + ) +{ + UINTN Hour, Year; + CHAR16 AmPm; + + AmPm = 'a'; + Hour = Time->Hour; + if (Time->Hour == 0) { + Hour = 12; + } else if (Time->Hour >= 12) { + AmPm = 'p'; + if (Time->Hour >= 13) { + Hour -= 12; + } + } + + Year = Time->Year % 100; + + // bugbug: for now just print it any old way + SPrint (Buffer, 0, L"%02d/%02d/%02d %02d:%02d%c", + Time->Month, + Time->Day, + Year, + Hour, + Time->Minute, + AmPm + ); +} + + + + +VOID +DumpHex ( + IN UINTN Indent, + IN UINTN Offset, + IN UINTN DataSize, + IN VOID *UserData + ) +{ + CHAR8 *Data, Val[50], Str[20], c; + UINTN Size, Index; + + UINTN ScreenCount; + UINTN TempColumn; + UINTN ScreenSize; + CHAR16 ReturnStr[1]; + + + uefi_call_wrapper(ST->ConOut->QueryMode, 4, ST->ConOut, ST->ConOut->Mode->Mode, &TempColumn, &ScreenSize); + ScreenCount = 0; + ScreenSize -= 2; + + Data = UserData; + while (DataSize) { + Size = 16; + if (Size > DataSize) { + Size = DataSize; + } + + for (Index=0; Index < Size; Index += 1) { + c = Data[Index]; + Val[Index*3+0] = Hex[c>>4]; + Val[Index*3+1] = Hex[c&0xF]; + Val[Index*3+2] = (Index == 7)?'-':' '; + Str[Index] = (c < ' ' || c > 'z') ? '.' : c; + } + + Val[Index*3] = 0; + Str[Index] = 0; + Print (L"%*a%X: %-.48a *%a*\n", Indent, "", Offset, Val, Str); + + Data += Size; + Offset += Size; + DataSize -= Size; + + ScreenCount++; + if (ScreenCount >= ScreenSize && ScreenSize != 0) { + // + // If ScreenSize == 0 we have the console redirected so don't + // block updates + // + ScreenCount = 0; + Print (L"Press Enter to continue :"); + Input (L"", ReturnStr, sizeof(ReturnStr)/sizeof(CHAR16)); + Print (L"\n"); + } + + } +} diff --git a/gnu-efi/lib/runtime/efirtlib.c b/gnu-efi/lib/runtime/efirtlib.c new file mode 100644 index 0000000..f782e4c --- /dev/null +++ b/gnu-efi/lib/runtime/efirtlib.c @@ -0,0 +1,145 @@ +/*++ + +Copyright (c) 1999 Intel Corporation + +Module Name: + + EfiRtLib.h + +Abstract: + + EFI Runtime library functions + + + +Revision History + +--*/ + +#include "efi.h" +#include "efilib.h" +#include "efirtlib.h" + +#ifndef __GNUC__ +#pragma RUNTIME_CODE(RtZeroMem) +#endif +VOID +RUNTIMEFUNCTION +RtZeroMem ( + IN VOID *Buffer, + IN UINTN Size + ) +{ + INT8 *pt; + + pt = Buffer; + while (Size--) { + *(pt++) = 0; + } +} + +#ifndef __GNUC__ +#pragma RUNTIME_CODE(RtSetMem) +#endif +VOID +RUNTIMEFUNCTION +RtSetMem ( + IN VOID *Buffer, + IN UINTN Size, + IN UINT8 Value + ) +{ + INT8 *pt; + + pt = Buffer; + while (Size--) { + *(pt++) = Value; + } +} + +#ifndef __GNUC__ +#pragma RUNTIME_CODE(RtCopyMem) +#endif +VOID +RUNTIMEFUNCTION +RtCopyMem ( + IN VOID *Dest, + IN CONST VOID *Src, + IN UINTN len + ) +{ + CHAR8 *d; + CONST CHAR8 *s = Src; + d = Dest; + while (len--) { + *(d++) = *(s++); + } +} + +#ifndef __GNUC__ +#pragma RUNTIME_CODE(RtCompareMem) +#endif +INTN +RUNTIMEFUNCTION +RtCompareMem ( + IN CONST VOID *Dest, + IN CONST VOID *Src, + IN UINTN len + ) +{ + CONST CHAR8 *d = Dest, *s = Src; + while (len--) { + if (*d != *s) { + return *d - *s; + } + + d += 1; + s += 1; + } + + return 0; +} + +#ifndef __GNUC__ +#pragma RUNTIME_CODE(RtCompareGuid) +#endif +INTN +RUNTIMEFUNCTION +RtCompareGuid ( + IN EFI_GUID *Guid1, + IN EFI_GUID *Guid2 + ) +/*++ + +Routine Description: + + Compares to GUIDs + +Arguments: + + Guid1 - guid to compare + Guid2 - guid to compare + +Returns: + = 0 if Guid1 == Guid2 + +--*/ +{ + INT32 *g1, *g2, r; + + // + // Compare 32 bits at a time + // + + g1 = (INT32 *) Guid1; + g2 = (INT32 *) Guid2; + + r = g1[0] - g2[0]; + r |= g1[1] - g2[1]; + r |= g1[2] - g2[2]; + r |= g1[3] - g2[3]; + + return r; +} + + diff --git a/gnu-efi/lib/runtime/rtdata.c b/gnu-efi/lib/runtime/rtdata.c new file mode 100644 index 0000000..3efcbf3 --- /dev/null +++ b/gnu-efi/lib/runtime/rtdata.c @@ -0,0 +1,65 @@ +/*++ + +Copyright (c) 1998 Intel Corporation + +Module Name: + + data.c + +Abstract: + + EFI library global data + + + +Revision History + +--*/ + +#include "lib.h" + + +// +// These globals are runtime globals +// +// N.B. The Microsoft C compiler will only put the data in the +// right data section if it is explicitly initialized.. +// + +#ifndef __GNUC__ +#pragma BEGIN_RUNTIME_DATA() +#endif + +// +// RT - pointer to the runtime table +// + +EFI_RUNTIME_SERVICES *RT; + +// +// LibStandalone - TRUE if lib is linked in as part of the firmware. +// N.B. The EFI fw sets this value directly +// + +BOOLEAN LibFwInstance; + +// +// EFIDebug - Debug mask +// + +UINTN EFIDebug = EFI_DBUG_MASK; + +// +// LibRuntimeDebugOut - Runtime Debug Output device +// + +SIMPLE_TEXT_OUTPUT_INTERFACE *LibRuntimeDebugOut; + +// +// LibRuntimeRaiseTPL, LibRuntimeRestoreTPL - pointers to Runtime functions from the +// Boot Services Table +// + +EFI_RAISE_TPL LibRuntimeRaiseTPL = NULL; +EFI_RESTORE_TPL LibRuntimeRestoreTPL = NULL; + diff --git a/gnu-efi/lib/runtime/rtlock.c b/gnu-efi/lib/runtime/rtlock.c new file mode 100644 index 0000000..2eafdca --- /dev/null +++ b/gnu-efi/lib/runtime/rtlock.c @@ -0,0 +1,102 @@ +/*++ + +Copyright (c) 1998 Intel Corporation + +Module Name: + + lock.c + +Abstract: + + Implements FLOCK + + + +Revision History + +--*/ + + +#include "lib.h" + + + +#ifndef __GNUC__ +#pragma RUNTIME_CODE(RtAcquireLock) +#endif +VOID +RtAcquireLock ( + IN FLOCK *Lock + ) +/*++ + +Routine Description: + + Raising to the task priority level of the mutual exclusion + lock, and then acquires ownership of the lock. + +Arguments: + + Lock - The lock to acquire + +Returns: + + Lock owned + +--*/ +{ + if (BS) { + if (BS->RaiseTPL != NULL) { + Lock->OwnerTpl = uefi_call_wrapper(BS->RaiseTPL, 1, Lock->Tpl); + } + } + else { + if (LibRuntimeRaiseTPL != NULL) { + Lock->OwnerTpl = LibRuntimeRaiseTPL(Lock->Tpl); + } + } + Lock->Lock += 1; + ASSERT (Lock->Lock == 1); +} + + +#ifndef __GNUC__ +#pragma RUNTIME_CODE(RtAcquireLock) +#endif +VOID +RtReleaseLock ( + IN FLOCK *Lock + ) +/*++ + +Routine Description: + + Releases ownership of the mutual exclusion lock, and + restores the previous task priority level. + +Arguments: + + Lock - The lock to release + +Returns: + + Lock unowned + +--*/ +{ + EFI_TPL Tpl; + + Tpl = Lock->OwnerTpl; + ASSERT(Lock->Lock == 1); + Lock->Lock -= 1; + if (BS) { + if (BS->RestoreTPL != NULL) { + uefi_call_wrapper(BS->RestoreTPL, 1, Tpl); + } + } + else { + if (LibRuntimeRestoreTPL != NULL) { + LibRuntimeRestoreTPL(Tpl); + } + } +} diff --git a/gnu-efi/lib/runtime/rtstr.c b/gnu-efi/lib/runtime/rtstr.c new file mode 100644 index 0000000..802e7f4 --- /dev/null +++ b/gnu-efi/lib/runtime/rtstr.c @@ -0,0 +1,231 @@ +/*++ + +Copyright (c) 1998 Intel Corporation + +Module Name: + + str.c + +Abstract: + + String runtime functions + + +Revision History + +--*/ + +#include "lib.h" + +#ifndef __GNUC__ +#pragma RUNTIME_CODE(RtStrCmp) +#endif +INTN +RUNTIMEFUNCTION +RtStrCmp ( + IN CONST CHAR16 *s1, + IN CONST CHAR16 *s2 + ) +// compare strings +{ + while (*s1) { + if (*s1 != *s2) { + break; + } + + s1 += 1; + s2 += 1; + } + + return *s1 - *s2; +} + +#ifndef __GNUC__ +#pragma RUNTIME_CODE(RtStrCpy) +#endif +VOID +RUNTIMEFUNCTION +RtStrCpy ( + IN CHAR16 *Dest, + IN CONST CHAR16 *Src + ) +// copy strings +{ + while (*Src) { + *(Dest++) = *(Src++); + } + *Dest = 0; +} + +#ifndef __GNUC__ +#pragma RUNTIME_CODE(RtStrnCpy) +#endif +VOID +RUNTIMEFUNCTION +RtStrnCpy ( + IN CHAR16 *Dest, + IN CONST CHAR16 *Src, + IN UINTN Len + ) +// copy strings +{ + UINTN Size = RtStrnLen(Src, Len); + if (Size != Len) + RtSetMem(Dest + Size, (Len - Size) * sizeof(CHAR16), '\0'); + RtCopyMem(Dest, Src, Size * sizeof(CHAR16)); +} + +#ifndef __GNUC__ +#pragma RUNTIME_CODE(RtStpCpy) +#endif +CHAR16 * +RUNTIMEFUNCTION +RtStpCpy ( + IN CHAR16 *Dest, + IN CONST CHAR16 *Src + ) +// copy strings +{ + while (*Src) { + *(Dest++) = *(Src++); + } + *Dest = 0; + return Dest; +} + +#ifndef __GNUC__ +#pragma RUNTIME_CODE(RtStpnCpy) +#endif +CHAR16 * +RUNTIMEFUNCTION +RtStpnCpy ( + IN CHAR16 *Dest, + IN CONST CHAR16 *Src, + IN UINTN Len + ) +// copy strings +{ + UINTN Size = RtStrnLen(Src, Len); + if (Size != Len) + RtSetMem(Dest + Size, (Len - Size) * sizeof(CHAR16), '\0'); + RtCopyMem(Dest, Src, Size * sizeof(CHAR16)); + return Dest + Size; +} + +#ifndef __GNUC__ +#pragma RUNTIME_CODE(RtStrCat) +#endif +VOID +RUNTIMEFUNCTION +RtStrCat ( + IN CHAR16 *Dest, + IN CONST CHAR16 *Src + ) +{ + RtStrCpy(Dest+RtStrLen(Dest), Src); +} + +#ifndef __GNUC__ +#pragma RUNTIME_CODE(RtStrnCat) +#endif +VOID +RUNTIMEFUNCTION +RtStrnCat ( + IN CHAR16 *Dest, + IN CONST CHAR16 *Src, + IN UINTN Len + ) +{ + UINTN DestSize, Size; + + DestSize = RtStrLen(Dest); + Size = RtStrnLen(Src, Len); + RtCopyMem(Dest + DestSize, Src, Size * sizeof(CHAR16)); + Dest[DestSize + Size] = '\0'; +} + +#ifndef __GNUC__ +#pragma RUNTIME_CODE(RtStrLen) +#endif +UINTN +RUNTIMEFUNCTION +RtStrLen ( + IN CONST CHAR16 *s1 + ) +// string length +{ + UINTN len; + + for (len=0; *s1; s1+=1, len+=1) ; + return len; +} + +#ifndef __GNUC__ +#pragma RUNTIME_CODE(RtStrnLen) +#endif +UINTN +RUNTIMEFUNCTION +RtStrnLen ( + IN CONST CHAR16 *s1, + IN UINTN Len + ) +// string length +{ + UINTN i; + for (i = 0; *s1 && i < Len; i++) + s1++; + return i; +} + +#ifndef __GNUC__ +#pragma RUNTIME_CODE(RtStrSize) +#endif +UINTN +RUNTIMEFUNCTION +RtStrSize ( + IN CONST CHAR16 *s1 + ) +// string size +{ + UINTN len; + + for (len=0; *s1; s1+=1, len+=1) ; + return (len + 1) * sizeof(CHAR16); +} + +#ifndef __GNUC__ +#pragma RUNTIME_CODE(RtBCDtoDecimal) +#endif +UINT8 +RUNTIMEFUNCTION +RtBCDtoDecimal( + IN UINT8 BcdValue + ) +{ + UINTN High, Low; + + High = BcdValue >> 4; + Low = BcdValue - (High << 4); + + return ((UINT8)(Low + (High * 10))); +} + + +#ifndef __GNUC__ +#pragma RUNTIME_CODE(RtDecimaltoBCD) +#endif +UINT8 +RUNTIMEFUNCTION +RtDecimaltoBCD ( + IN UINT8 DecValue + ) +{ + UINTN High, Low; + + High = DecValue / 10; + Low = DecValue - (High * 10); + + return ((UINT8)(Low + (High << 4))); +} + + diff --git a/gnu-efi/lib/runtime/vm.c b/gnu-efi/lib/runtime/vm.c new file mode 100644 index 0000000..26e0c8e --- /dev/null +++ b/gnu-efi/lib/runtime/vm.c @@ -0,0 +1,105 @@ +/*++ + +Copyright (c) 1998 Intel Corporation + +Module Name: + + vm.c + +Abstract: + + EFI Hell to remap runtime address into the new virual address space + that was registered by the OS for RT calls. + + So the code image needs to be relocated. All pointers need to be + manually fixed up since the address map changes. + + GOOD LUCK NOT HAVING BUGS IN YOUR CODE! PLEASE TEST A LOT. MAKE SURE + EXIT BOOTSERVICES OVER WRITES ALL BOOTSERVICE MEMORY & DATA SPACES WHEN + YOU TEST. + +Revision History + +--*/ + +#include "lib.h" + +#ifndef __GNUC__ +#pragma RUNTIME_CODE(RtLibEnableVirtualMappings) +#endif +VOID +RUNTIMEFUNCTION +RtLibEnableVirtualMappings ( + VOID + ) +{ + EFI_CONVERT_POINTER ConvertPointer; + + // + // If this copy of the lib is linked into the firmware, then + // do not update the pointers yet. + // + + if (!LibFwInstance) { + + // + // Different components are updating to the new virtual + // mappings at differnt times. The only function that + // is safe to call at this notification is ConvertAddress + // + + ConvertPointer = RT->ConvertPointer; + + // + // Fix any pointers that the lib created, that may be needed + // during runtime. + // + + ConvertPointer (EFI_INTERNAL_PTR, (VOID **)&RT); + ConvertPointer (EFI_OPTIONAL_PTR, (VOID **)&LibRuntimeDebugOut); + + ConvertPointer (EFI_INTERNAL_PTR, (VOID **)&LibRuntimeRaiseTPL); + ConvertPointer (EFI_INTERNAL_PTR, (VOID **)&LibRuntimeRestoreTPL); + + // that was it :^) + } +} + + +#ifndef __GNUC__ +#pragma RUNTIME_CODE(RtConvertList) +#endif +VOID +RUNTIMEFUNCTION +RtConvertList ( + IN UINTN DebugDisposition, + IN OUT LIST_ENTRY *ListHead + ) +{ + LIST_ENTRY *Link; + LIST_ENTRY *NextLink; + EFI_CONVERT_POINTER ConvertPointer; + + ConvertPointer = RT->ConvertPointer; + + // + // Convert all the Flink & Blink pointers in the list + // + + Link = ListHead; + do { + NextLink = Link->Flink; + + ConvertPointer ( + Link->Flink == ListHead ? DebugDisposition : 0, + (VOID **)&Link->Flink + ); + + ConvertPointer ( + Link->Blink == ListHead ? DebugDisposition : 0, + (VOID **)&Link->Blink + ); + + Link = NextLink; + } while (Link != ListHead); +} diff --git a/gnu-efi/lib/smbios.c b/gnu-efi/lib/smbios.c new file mode 100644 index 0000000..d349fb6 --- /dev/null +++ b/gnu-efi/lib/smbios.c @@ -0,0 +1,135 @@ +/*++ + +Copyright (c) 2000 Intel Corporation + +Module Name: + + Smbios.c + +Abstract: + + Lib fucntions for SMBIOS. Used to get system serial number and GUID + +Revision History + +--*/ + +#include "lib.h" + +/* + * We convert 32 bit values to pointers. In 64 bit mode the compiler will issue a + * warning stating that the value is too small for the pointer: + * "warning: cast to pointer from integer of different size [-Wint-to-pointer-cast]" + * we can safely ignore them here. + */ +#ifdef __GNUC__ +#pragma GCC diagnostic ignored "-Wint-to-pointer-cast" +#endif + +EFI_STATUS +LibGetSmbiosSystemGuidAndSerialNumber ( + IN EFI_GUID *SystemGuid, + OUT CHAR8 **SystemSerialNumber + ) +{ + EFI_STATUS Status; + SMBIOS_STRUCTURE_TABLE *SmbiosTable; + SMBIOS_STRUCTURE_POINTER Smbios; + SMBIOS_STRUCTURE_POINTER SmbiosEnd; + UINT16 Index; + + Status = LibGetSystemConfigurationTable(&SMBIOSTableGuid, (VOID**)&SmbiosTable); + if (EFI_ERROR(Status)) { + return EFI_NOT_FOUND; + } + + Smbios.Hdr = (SMBIOS_HEADER *)SmbiosTable->TableAddress; + SmbiosEnd.Raw = (UINT8 *)(SmbiosTable->TableAddress + SmbiosTable->TableLength); + for (Index = 0; Index < SmbiosTable->TableLength ; Index++) { + if (Smbios.Hdr->Type == 1) { + if (Smbios.Hdr->Length < 0x19) { + // + // Older version did not support Guid and Serial number + // + continue; + } + + // + // SMBIOS tables are byte packed so we need to do a byte copy to + // prevend alignment faults on IA-64. + + CopyMem (SystemGuid, &Smbios.Type1->Uuid, sizeof(EFI_GUID)); + *SystemSerialNumber = LibGetSmbiosString(&Smbios, Smbios.Type1->SerialNumber); + return EFI_SUCCESS; + } + + // + // Make Smbios point to the next record + // + LibGetSmbiosString (&Smbios, -1); + + if (Smbios.Raw >= SmbiosEnd.Raw) { + // + // SMBIOS 2.1 incorrectly stated the length of SmbiosTable as 0x1e. + // given this we must double check against the lenght of + /// the structure. My home PC has this bug.ruthard + // + return EFI_SUCCESS; + } + } + + return EFI_SUCCESS; +} + +CHAR8* +LibGetSmbiosString ( + IN SMBIOS_STRUCTURE_POINTER *Smbios, + IN UINT16 StringNumber + ) +/*++ + + Return SMBIOS string given the string number. + + Arguments: + Smbios - Pointer to SMBIOS structure + StringNumber - String number to return. -1 is used to skip all strings and + point to the next SMBIOS structure. + + Returns: + Pointer to string, or pointer to next SMBIOS strcuture if StringNumber == -1 +--*/ +{ + UINT16 Index; + CHAR8 *String; + + // + // Skip over formatted section + // + String = (CHAR8 *)(Smbios->Raw + Smbios->Hdr->Length); + + // + // Look through unformated section + // + for (Index = 1; Index <= StringNumber; Index++) { + if (StringNumber == Index) { + return String; + } + + // + // Skip string + // + for (; *String != 0; String++); + String++; + + if (*String == 0) { + // + // If double NULL then we are done. + // Retrun pointer to next structure in Smbios. + // if you pass in a -1 you will always get here + // + Smbios->Raw = (UINT8 *)++String; + return NULL; + } + } + return NULL; +} diff --git a/gnu-efi/lib/sread.c b/gnu-efi/lib/sread.c new file mode 100644 index 0000000..888f954 --- /dev/null +++ b/gnu-efi/lib/sread.c @@ -0,0 +1,358 @@ +/*++ + +Copyright (c) 1998 Intel Corporation + +Module Name: + + sread.c + +Abstract: + + Simple read file access + + + +Revision History + +--*/ + +#include "lib.h" + +#define SIMPLE_READ_SIGNATURE EFI_SIGNATURE_32('s','r','d','r') +typedef struct _SIMPLE_READ_FILE { + UINTN Signature; + BOOLEAN FreeBuffer; + VOID *Source; + UINTN SourceSize; + EFI_FILE_HANDLE FileHandle; +} SIMPLE_READ_HANDLE; + + + +EFI_STATUS +OpenSimpleReadFile ( + IN BOOLEAN BootPolicy, + IN VOID *SourceBuffer OPTIONAL, + IN UINTN SourceSize, + IN OUT EFI_DEVICE_PATH **FilePath, + OUT EFI_HANDLE *DeviceHandle, + OUT SIMPLE_READ_FILE *SimpleReadHandle + ) +/*++ + +Routine Description: + + Opens a file for (simple) reading. The simple read abstraction + will access the file either from a memory copy, from a file + system interface, or from the load file interface. + +Arguments: + +Returns: + + A handle to access the file + +--*/ +{ + SIMPLE_READ_HANDLE *FHand; + EFI_DEVICE_PATH *UserFilePath; + EFI_DEVICE_PATH *TempFilePath; + EFI_DEVICE_PATH *TempFilePathPtr; + FILEPATH_DEVICE_PATH *FilePathNode; + EFI_FILE_HANDLE FileHandle, LastHandle; + EFI_STATUS Status; + EFI_LOAD_FILE_INTERFACE *LoadFile; + + FHand = NULL; + UserFilePath = *FilePath; + + // + // Allocate a new simple read handle structure + // + + FHand = AllocateZeroPool (sizeof(SIMPLE_READ_HANDLE)); + if (!FHand) { + Status = EFI_OUT_OF_RESOURCES; + goto Done; + } + + *SimpleReadHandle = (SIMPLE_READ_FILE) FHand; + FHand->Signature = SIMPLE_READ_SIGNATURE; + + // + // If the caller passed a copy of the file, then just use it + // + + if (SourceBuffer) { + FHand->Source = SourceBuffer; + FHand->SourceSize = SourceSize; + *DeviceHandle = NULL; + Status = EFI_SUCCESS; + goto Done; + } + + // + // Attempt to access the file via a file system interface + // + + FileHandle = NULL; + Status = uefi_call_wrapper(BS->LocateDevicePath, 3, &FileSystemProtocol, FilePath, DeviceHandle); + if (!EFI_ERROR(Status)) { + FileHandle = LibOpenRoot (*DeviceHandle); + } + + Status = FileHandle ? EFI_SUCCESS : EFI_UNSUPPORTED; + + // + // To access as a filesystem, the filepath should only + // contain filepath components. Follow the filepath nodes + // and find the target file + // + + FilePathNode = (FILEPATH_DEVICE_PATH *) *FilePath; + while (!IsDevicePathEnd(&FilePathNode->Header)) { + + // + // For filesystem access each node should be a filepath component + // + + if (DevicePathType(&FilePathNode->Header) != MEDIA_DEVICE_PATH || + DevicePathSubType(&FilePathNode->Header) != MEDIA_FILEPATH_DP) { + Status = EFI_UNSUPPORTED; + } + + // + // If there's been an error, stop + // + + if (EFI_ERROR(Status)) { + break; + } + + // + // Open this file path node + // + + LastHandle = FileHandle; + FileHandle = NULL; + + Status = uefi_call_wrapper( + LastHandle->Open, + 5, + LastHandle, + &FileHandle, + FilePathNode->PathName, + EFI_FILE_MODE_READ, + 0 + ); + + // + // Close the last node + // + + uefi_call_wrapper(LastHandle->Close, 1, LastHandle); + + // + // Get the next node + // + + FilePathNode = (FILEPATH_DEVICE_PATH *) NextDevicePathNode(&FilePathNode->Header); + } + + // + // If success, return the FHand + // + + if (!EFI_ERROR(Status)) { + ASSERT(FileHandle); + FHand->FileHandle = FileHandle; + goto Done; + } + + // + // Cleanup from filesystem access + // + + if (FileHandle) { + uefi_call_wrapper(FileHandle->Close, 1, FileHandle); + FileHandle = NULL; + *FilePath = UserFilePath; + } + + // + // If the error is something other then unsupported, return it + // + + if (Status != EFI_UNSUPPORTED) { + goto Done; + } + + // + // Attempt to access the file via the load file protocol + // + + Status = LibDevicePathToInterface (&LoadFileProtocol, *FilePath, (VOID*)&LoadFile); + if (!EFI_ERROR(Status)) { + + TempFilePath = DuplicateDevicePath (*FilePath); + + TempFilePathPtr = TempFilePath; + + Status = uefi_call_wrapper(BS->LocateDevicePath, 3, &LoadFileProtocol, &TempFilePath, DeviceHandle); + + FreePool (TempFilePathPtr); + + // + // Determine the size of buffer needed to hold the file + // + + SourceSize = 0; + Status = uefi_call_wrapper( + LoadFile->LoadFile, + 5, + LoadFile, + *FilePath, + BootPolicy, + &SourceSize, + NULL + ); + + // + // We expect a buffer too small error to inform us + // of the buffer size needed + // + + if (Status == EFI_BUFFER_TOO_SMALL) { + SourceBuffer = AllocatePool (SourceSize); + + if (SourceBuffer) { + FHand->FreeBuffer = TRUE; + FHand->Source = SourceBuffer; + FHand->SourceSize = SourceSize; + + Status = uefi_call_wrapper( + LoadFile->LoadFile, + 5, + LoadFile, + *FilePath, + BootPolicy, + &SourceSize, + SourceBuffer + ); + } + } + + // + // If success, return FHand + // + + if (!EFI_ERROR(Status) || Status == EFI_ALREADY_STARTED) { + goto Done; + } + } + + // + // Nothing else to try + // + + DEBUG ((D_LOAD|D_WARN, "OpenSimpleReadFile: Device did not support a known load protocol\n")); + Status = EFI_UNSUPPORTED; + +Done: + + // + // If the file was not accessed, clean up + // + if (EFI_ERROR(Status) && (Status != EFI_ALREADY_STARTED)) { + if (FHand) { + if (FHand->FreeBuffer) { + FreePool (FHand->Source); + } + + FreePool (FHand); + } + } + + return Status; +} + +EFI_STATUS +ReadSimpleReadFile ( + IN SIMPLE_READ_FILE UserHandle, + IN UINTN Offset, + IN OUT UINTN *ReadSize, + OUT VOID *Buffer + ) +{ + UINTN EndPos; + SIMPLE_READ_HANDLE *FHand; + EFI_STATUS Status; + + FHand = UserHandle; + ASSERT (FHand->Signature == SIMPLE_READ_SIGNATURE); + if (FHand->Source) { + + // + // Move data from our local copy of the file + // + + EndPos = Offset + *ReadSize; + if (EndPos > FHand->SourceSize) { + *ReadSize = FHand->SourceSize - Offset; + if (Offset >= FHand->SourceSize) { + *ReadSize = 0; + } + } + + CopyMem (Buffer, (CHAR8 *) FHand->Source + Offset, *ReadSize); + Status = EFI_SUCCESS; + + } else { + + // + // Read data from the file + // + + Status = uefi_call_wrapper(FHand->FileHandle->SetPosition, 2, FHand->FileHandle, Offset); + + if (!EFI_ERROR(Status)) { + Status = uefi_call_wrapper(FHand->FileHandle->Read, 3, FHand->FileHandle, ReadSize, Buffer); + } + } + + return Status; +} + + +VOID +CloseSimpleReadFile ( + IN SIMPLE_READ_FILE UserHandle + ) +{ + SIMPLE_READ_HANDLE *FHand; + + FHand = UserHandle; + ASSERT (FHand->Signature == SIMPLE_READ_SIGNATURE); + + // + // Free any file handle we opened + // + + if (FHand->FileHandle) { + uefi_call_wrapper(FHand->FileHandle->Close, 1, FHand->FileHandle); + } + + // + // If we allocated the Source buffer, free it + // + + if (FHand->FreeBuffer) { + FreePool (FHand->Source); + } + + // + // Done with this simple read file handle + // + + FreePool (FHand); +} diff --git a/gnu-efi/lib/str.c b/gnu-efi/lib/str.c new file mode 100644 index 0000000..9a89f30 --- /dev/null +++ b/gnu-efi/lib/str.c @@ -0,0 +1,432 @@ +/*++ + +Copyright (c) 1998 Intel Corporation + +Module Name: + + str.c + +Abstract: + + + + +Revision History + +--*/ + +#include "lib.h" + + +INTN +StrCmp ( + IN CONST CHAR16 *s1, + IN CONST CHAR16 *s2 + ) +// compare strings +{ + return RtStrCmp(s1, s2); +} + +INTN +StrnCmp ( + IN CONST CHAR16 *s1, + IN CONST CHAR16 *s2, + IN UINTN len + ) +// compare strings +{ + while (*s1 && len) { + if (*s1 != *s2) { + break; + } + + s1 += 1; + s2 += 1; + len -= 1; + } + + return len ? *s1 - *s2 : 0; +} + + +INTN EFIAPI +LibStubStriCmp ( + IN EFI_UNICODE_COLLATION_INTERFACE *This EFI_UNUSED, + IN CHAR16 *s1, + IN CHAR16 *s2 + ) +{ + return StrCmp (s1, s2); +} + +VOID EFIAPI +LibStubStrLwrUpr ( + IN EFI_UNICODE_COLLATION_INTERFACE *This EFI_UNUSED, + IN CHAR16 *Str EFI_UNUSED + ) +{ +} + +INTN +StriCmp ( + IN CONST CHAR16 *s1, + IN CONST CHAR16 *s2 + ) +// compare strings +{ + if (UnicodeInterface == &LibStubUnicodeInterface) + return UnicodeInterface->StriColl(UnicodeInterface, (CHAR16 *)s1, (CHAR16 *)s2); + else + return uefi_call_wrapper(UnicodeInterface->StriColl, 3, UnicodeInterface, (CHAR16 *)s1, (CHAR16 *)s2); +} + +VOID +StrLwr ( + IN CHAR16 *Str + ) +// lwoer case string +{ + if (UnicodeInterface == &LibStubUnicodeInterface) + UnicodeInterface->StrLwr(UnicodeInterface, Str); + else uefi_call_wrapper(UnicodeInterface->StrLwr, 2, UnicodeInterface, Str); +} + +VOID +StrUpr ( + IN CHAR16 *Str + ) +// upper case string +{ + if (UnicodeInterface == &LibStubUnicodeInterface) + UnicodeInterface->StrUpr(UnicodeInterface, Str); + else uefi_call_wrapper(UnicodeInterface->StrUpr, 2, UnicodeInterface, Str); +} + +VOID +StrCpy ( + IN CHAR16 *Dest, + IN CONST CHAR16 *Src + ) +// copy strings +{ + RtStrCpy (Dest, Src); +} + +VOID +StrnCpy ( + IN CHAR16 *Dest, + IN CONST CHAR16 *Src, + IN UINTN Len + ) +// copy strings +{ + RtStrnCpy (Dest, Src, Len); +} + +CHAR16 * +StpCpy ( + IN CHAR16 *Dest, + IN CONST CHAR16 *Src + ) +// copy strings +{ + return RtStpCpy (Dest, Src); +} + +CHAR16 * +StpnCpy ( + IN CHAR16 *Dest, + IN CONST CHAR16 *Src, + IN UINTN Len + ) +// copy strings +{ + return RtStpnCpy (Dest, Src, Len); +} + +VOID +StrCat ( + IN CHAR16 *Dest, + IN CONST CHAR16 *Src + ) +{ + RtStrCat(Dest, Src); +} + +VOID +StrnCat ( + IN CHAR16 *Dest, + IN CONST CHAR16 *Src, + IN UINTN Len + ) +{ + RtStrnCat(Dest, Src, Len); +} + + +UINTN +StrnLen ( + IN CONST CHAR16 *s1, + IN UINTN Len + ) +// string length +{ + return RtStrnLen(s1, Len); +} + +UINTN +StrLen ( + IN CONST CHAR16 *s1 + ) +// string length +{ + return RtStrLen(s1); +} + +UINTN +StrSize ( + IN CONST CHAR16 *s1 + ) +// string size +{ + return RtStrSize(s1); +} + +CHAR16 * +StrDuplicate ( + IN CONST CHAR16 *Src + ) +// duplicate a string +{ + CHAR16 *Dest; + UINTN Size; + + Size = StrSize(Src); + Dest = AllocatePool (Size); + if (Dest) { + CopyMem (Dest, Src, Size); + } + return Dest; +} + +UINTN +strlena ( + IN CONST CHAR8 *s1 + ) +// string length +{ + UINTN len; + + for (len=0; *s1; s1+=1, len+=1) ; + return len; +} + +UINTN +strcmpa ( + IN CONST CHAR8 *s1, + IN CONST CHAR8 *s2 + ) +// compare strings +{ + while (*s1) { + if (*s1 != *s2) { + break; + } + + s1 += 1; + s2 += 1; + } + + return *s1 - *s2; +} + +UINTN +strncmpa ( + IN CONST CHAR8 *s1, + IN CONST CHAR8 *s2, + IN UINTN len + ) +// compare strings +{ + while (*s1 && len) { + if (*s1 != *s2) { + break; + } + + s1 += 1; + s2 += 1; + len -= 1; + } + + return len ? *s1 - *s2 : 0; +} + + + +UINTN +xtoi ( + CONST CHAR16 *str + ) +// convert hex string to uint +{ + UINTN u; + CHAR16 c; + + // skip preceeding white space + while (*str && *str == ' ') { + str += 1; + } + + // convert hex digits + u = 0; + while ((c = *(str++))) { + if (c >= 'a' && c <= 'f') { + c -= 'a' - 'A'; + } + + if ((c >= '0' && c <= '9') || (c >= 'A' && c <= 'F')) { + u = (u << 4) | (c - (c >= 'A' ? 'A'-10 : '0')); + } else { + break; + } + } + + return u; +} + +UINTN +Atoi ( + CONST CHAR16 *str + ) +// convert hex string to uint +{ + UINTN u; + CHAR16 c; + + // skip preceeding white space + while (*str && *str == ' ') { + str += 1; + } + + // convert digits + u = 0; + while ((c = *(str++))) { + if (c >= '0' && c <= '9') { + u = (u * 10) + c - '0'; + } else { + break; + } + } + + return u; +} + +BOOLEAN +MetaMatch ( + IN CHAR16 *String, + IN CHAR16 *Pattern + ) +{ + CHAR16 c, p, l; + + for (; ;) { + p = *Pattern; + Pattern += 1; + + switch (p) { + case 0: + // End of pattern. If end of string, TRUE match + return *String ? FALSE : TRUE; + + case '*': + // Match zero or more chars + while (*String) { + if (MetaMatch (String, Pattern)) { + return TRUE; + } + String += 1; + } + return MetaMatch (String, Pattern); + + case '?': + // Match any one char + if (!*String) { + return FALSE; + } + String += 1; + break; + + case '[': + // Match char set + c = *String; + if (!c) { + return FALSE; // syntax problem + } + + l = 0; + while ((p = *Pattern++)) { + if (p == ']') { + return FALSE; + } + + if (p == '-') { // if range of chars, + p = *Pattern; // get high range + if (p == 0 || p == ']') { + return FALSE; // syntax problem + } + + if (c >= l && c <= p) { // if in range, + break; // it's a match + } + } + + l = p; + if (c == p) { // if char matches + break; // move on + } + } + + // skip to end of match char set + while (p && p != ']') { + p = *Pattern; + Pattern += 1; + } + + String += 1; + break; + + default: + c = *String; + if (c != p) { + return FALSE; + } + + String += 1; + break; + } + } +} + + +BOOLEAN EFIAPI +LibStubMetaiMatch ( + IN EFI_UNICODE_COLLATION_INTERFACE *This EFI_UNUSED, + IN CHAR16 *String, + IN CHAR16 *Pattern + ) +{ + return MetaMatch (String, Pattern); +} + + +BOOLEAN +MetaiMatch ( + IN CHAR16 *String, + IN CHAR16 *Pattern + ) +{ + if (UnicodeInterface == &LibStubUnicodeInterface) + return UnicodeInterface->MetaiMatch(UnicodeInterface, String, Pattern); + else return uefi_call_wrapper(UnicodeInterface->MetaiMatch, 3, UnicodeInterface, String, Pattern); +} diff --git a/gnu-efi/lib/x86_64/callwrap.c b/gnu-efi/lib/x86_64/callwrap.c new file mode 100644 index 0000000..30a5322 --- /dev/null +++ b/gnu-efi/lib/x86_64/callwrap.c @@ -0,0 +1,40 @@ +/* + * Convert SysV calling convention to EFI x86_64 calling convention + * + * Copyright (C) 2007-2010 Intel Corp + * Bibo Mao + * Chandramouli Narayanan + * Huang Ying + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * - Neither the name of Hewlett-Packard Co. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANYDIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF + * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* uefi_call_wrapper() is a macro in efibind.h */ diff --git a/gnu-efi/lib/x86_64/efi_stub.S b/gnu-efi/lib/x86_64/efi_stub.S new file mode 100644 index 0000000..b431255 --- /dev/null +++ b/gnu-efi/lib/x86_64/efi_stub.S @@ -0,0 +1,189 @@ +/* + * Function calling ABI conversion from Linux to EFI for x86_64 + * + * Copyright (C) 2007 Intel Corp + * Bibo Mao + * Huang Ying + * Copyright (C) 2012 Felipe Contreras + */ + +#if !defined(HAVE_USE_MS_ABI) +/* + * EFI calling conventions are documented at: + * http://msdn.microsoft.com/en-us/library/ms235286%28v=vs.80%29.aspx + * ELF calling conventions are documented at: + * http://www.x86-64.org/documentation/abi.pdf + * + * Basically here are the conversion rules: + * a) our function pointer is in %rdi + * b) rsi through r8 (elf) aka rcx through r9 (ms) require stack space + * on the MS side even though it's not getting used at all. + * c) 8(%rsp) is always aligned to 16 in ELF, so %rsp is shifted 8 bytes extra + * d) arguments are as follows: (elf -> ms) + * 1) rdi -> rcx (32 saved) + * 2) rsi -> rdx (32 saved) + * 3) rdx -> r8 (32 saved) + * 4) rcx -> r9 (32 saved) + * 5) r8 -> 32(%rsp) (32 saved) + * 6) r9 -> 40(%rsp) (48 saved) + * 7) 8(%rsp) -> 48(%rsp) (48 saved) + * 8) 16(%rsp) -> 56(%rsp) (64 saved) + * 9) 24(%rsp) -> 64(%rsp) (64 saved) + * 10) 32(%rsp) -> 72(%rsp) (80 saved) + * e) because the first argument we recieve in a thunker is actually the + * function to be called, arguments are offset as such: + * 0) rdi -> caller + * 1) rsi -> rcx (32 saved) + * 2) rdx -> rdx (32 saved) + * 3) rcx -> r8 (32 saved) + * 4) r8 -> r9 (32 saved) + * 5) r9 -> 32(%rsp) (32 saved) + * 6) 8(%rsp) -> 40(%rsp) (48 saved) + * 7) 16(%rsp) -> 48(%rsp) (48 saved) + * 8) 24(%rsp) -> 56(%rsp) (64 saved) + * 9) 32(%rsp) -> 64(%rsp) (64 saved) + * 10) 40(%rsp) -> 72(%rsp) (80 saved) + * f) arguments need to be moved in opposite order to avoid clobbering + */ + +#define ENTRY(name) \ + .globl name; \ + name: + +ENTRY(efi_call0) + subq $40, %rsp + call *%rdi + addq $40, %rsp + ret + +ENTRY(efi_call1) + subq $40, %rsp + mov %rsi, %rcx + call *%rdi + addq $40, %rsp + ret + +ENTRY(efi_call2) + subq $40, %rsp + /* mov %rdx, %rdx */ + mov %rsi, %rcx + call *%rdi + addq $40, %rsp + ret + +ENTRY(efi_call3) + subq $40, %rsp + mov %rcx, %r8 + /* mov %rdx, %rdx */ + mov %rsi, %rcx + call *%rdi + addq $40, %rsp + ret + +ENTRY(efi_call4) + subq $40, %rsp + mov %r8, %r9 + mov %rcx, %r8 + /* mov %rdx, %rdx */ + mov %rsi, %rcx + call *%rdi + addq $40, %rsp + ret + +ENTRY(efi_call5) + subq $40, %rsp + mov %r9, 32(%rsp) + mov %r8, %r9 + mov %rcx, %r8 + /* mov %rdx, %rdx */ + mov %rsi, %rcx + call *%rdi + addq $40, %rsp + ret + +ENTRY(efi_call6) + subq $56, %rsp + mov 56+8(%rsp), %rax + mov %rax, 40(%rsp) + mov %r9, 32(%rsp) + mov %r8, %r9 + mov %rcx, %r8 + /* mov %rdx, %rdx */ + mov %rsi, %rcx + call *%rdi + addq $56, %rsp + ret + +ENTRY(efi_call7) + subq $56, %rsp + mov 56+16(%rsp), %rax + mov %rax, 48(%rsp) + mov 56+8(%rsp), %rax + mov %rax, 40(%rsp) + mov %r9, 32(%rsp) + mov %r8, %r9 + mov %rcx, %r8 + /* mov %rdx, %rdx */ + mov %rsi, %rcx + call *%rdi + addq $56, %rsp + ret + +ENTRY(efi_call8) + subq $72, %rsp + mov 72+24(%rsp), %rax + mov %rax, 56(%rsp) + mov 72+16(%rsp), %rax + mov %rax, 48(%rsp) + mov 72+8(%rsp), %rax + mov %rax, 40(%rsp) + mov %r9, 32(%rsp) + mov %r8, %r9 + mov %rcx, %r8 + /* mov %rdx, %rdx */ + mov %rsi, %rcx + call *%rdi + addq $72, %rsp + ret + +ENTRY(efi_call9) + subq $72, %rsp + mov 72+32(%rsp), %rax + mov %rax, 64(%rsp) + mov 72+24(%rsp), %rax + mov %rax, 56(%rsp) + mov 72+16(%rsp), %rax + mov %rax, 48(%rsp) + mov 72+8(%rsp), %rax + mov %rax, 40(%rsp) + mov %r9, 32(%rsp) + mov %r8, %r9 + mov %rcx, %r8 + /* mov %rdx, %rdx */ + mov %rsi, %rcx + call *%rdi + addq $72, %rsp + ret + +ENTRY(efi_call10) + subq $88, %rsp + mov 88+40(%rsp), %rax + mov %rax, 72(%rsp) + mov 88+32(%rsp), %rax + mov %rax, 64(%rsp) + mov 88+24(%rsp), %rax + mov %rax, 56(%rsp) + mov 88+16(%rsp), %rax + mov %rax, 48(%rsp) + mov 88+8(%rsp), %rax + mov %rax, 40(%rsp) + mov %r9, 32(%rsp) + mov %r8, %r9 + mov %rcx, %r8 + /* mov %rdx, %rdx */ + mov %rsi, %rcx + call *%rdi + addq $88, %rsp + ret + +#endif diff --git a/gnu-efi/lib/x86_64/initplat.c b/gnu-efi/lib/x86_64/initplat.c new file mode 100644 index 0000000..7c887a6 --- /dev/null +++ b/gnu-efi/lib/x86_64/initplat.c @@ -0,0 +1,27 @@ +/*++ + +Copyright (c) 1998 Intel Corporation + +Module Name: + + initplat.c + +Abstract: + + + + +Revision History + +--*/ + +#include "lib.h" + +VOID +InitializeLibPlatform ( + IN EFI_HANDLE ImageHandle EFI_UNUSED, + IN EFI_SYSTEM_TABLE *SystemTable EFI_UNUSED + ) +{ +} + diff --git a/gnu-efi/lib/x86_64/math.c b/gnu-efi/lib/x86_64/math.c new file mode 100644 index 0000000..aa02431 --- /dev/null +++ b/gnu-efi/lib/x86_64/math.c @@ -0,0 +1,181 @@ +/*++ + +Copyright (c) 1998 Intel Corporation + +Module Name: + + math.c + +Abstract: + + + + +Revision History + +--*/ + +#include "lib.h" + + +// +// Declare runtime functions +// + +#ifdef RUNTIME_CODE +#ifndef __GNUC__ +#pragma RUNTIME_CODE(LShiftU64) +#pragma RUNTIME_CODE(RShiftU64) +#pragma RUNTIME_CODE(MultU64x32) +#pragma RUNTIME_CODE(DivU64x32) +#endif +#endif + +// +// +// + +UINT64 +LShiftU64 ( + IN UINT64 Operand, + IN UINTN Count + ) +// Left shift 64bit by 32bit and get a 64bit result +{ +#if defined(__GNUC__) || defined(_MSC_EXTENSIONS) + return Operand << Count; +#else + UINT64 Result; + _asm { + mov eax, dword ptr Operand[0] + mov edx, dword ptr Operand[4] + mov ecx, Count + and ecx, 63 + + shld edx, eax, cl + shl eax, cl + + cmp ecx, 32 + jc short ls10 + + mov edx, eax + xor eax, eax + +ls10: + mov dword ptr Result[0], eax + mov dword ptr Result[4], edx + } + + return Result; +#endif +} + +UINT64 +RShiftU64 ( + IN UINT64 Operand, + IN UINTN Count + ) +// Right shift 64bit by 32bit and get a 64bit result +{ +#if defined(__GNUC__) || defined(_MSC_EXTENSIONS) + return Operand >> Count; +#else + UINT64 Result; + _asm { + mov eax, dword ptr Operand[0] + mov edx, dword ptr Operand[4] + mov ecx, Count + and ecx, 63 + + shrd eax, edx, cl + shr edx, cl + + cmp ecx, 32 + jc short rs10 + + mov eax, edx + xor edx, edx + +rs10: + mov dword ptr Result[0], eax + mov dword ptr Result[4], edx + } + + return Result; +#endif +} + + +UINT64 +MultU64x32 ( + IN UINT64 Multiplicand, + IN UINTN Multiplier + ) +// Multiple 64bit by 32bit and get a 64bit result +{ +#if defined(__GNUC__) || defined(_MSC_EXTENSIONS) + return Multiplicand * Multiplier; +#else + UINT64 Result; + _asm { + mov eax, dword ptr Multiplicand[0] + mul Multiplier + mov dword ptr Result[0], eax + mov dword ptr Result[4], edx + mov eax, dword ptr Multiplicand[4] + mul Multiplier + add dword ptr Result[4], eax + } + + return Result; +#endif +} + +UINT64 +DivU64x32 ( + IN UINT64 Dividend, + IN UINTN Divisor, + OUT UINTN *Remainder OPTIONAL + ) +// divide 64bit by 32bit and get a 64bit result +// N.B. only works for 31bit divisors!! +{ +#if defined(__GNUC__) || defined(_MSC_EXTENSIONS) + if (Remainder) + *Remainder = Dividend % Divisor; + return Dividend / Divisor; +#else + UINT32 Rem; + UINT32 bit; + + ASSERT (Divisor != 0); + ASSERT ((Divisor >> 31) == 0); + + // + // For each bit in the dividend + // + + Rem = 0; + for (bit=0; bit < 64; bit++) { + _asm { + shl dword ptr Dividend[0], 1 ; shift rem:dividend left one + rcl dword ptr Dividend[4], 1 + rcl dword ptr Rem, 1 + + mov eax, Rem + cmp eax, Divisor ; Is Rem >= Divisor? + cmc ; No - do nothing + sbb eax, eax ; Else, + sub dword ptr Dividend[0], eax ; set low bit in dividen + and eax, Divisor ; and + sub Rem, eax ; subtract divisor + } + } + + if (Remainder) { + *Remainder = Rem; + } + + return Dividend; +#endif +} diff --git a/gnu-efi/lib/x86_64/setjmp.S b/gnu-efi/lib/x86_64/setjmp.S new file mode 100644 index 0000000..e870aef --- /dev/null +++ b/gnu-efi/lib/x86_64/setjmp.S @@ -0,0 +1,41 @@ + .text + .globl setjmp +#ifndef __MINGW32__ + .type setjmp, @function +#else + .def setjmp; .scl 2; .type 32; .endef +#endif +setjmp: + pop %rsi + movq %rbx,0x00(%rdi) + movq %rsp,0x08(%rdi) + push %rsi + movq %rbp,0x10(%rdi) + movq %r12,0x18(%rdi) + movq %r13,0x20(%rdi) + movq %r14,0x28(%rdi) + movq %r15,0x30(%rdi) + movq %rsi,0x38(%rdi) + xor %rax,%rax + ret + + .globl longjmp +#ifndef __MINGW32__ + .type longjmp, @function +#else + .def longjmp; .scl 2; .type 32; .endef +#endif +longjmp: + movl %esi, %eax + movq 0x00(%rdi), %rbx + movq 0x08(%rdi), %rsp + movq 0x10(%rdi), %rbp + movq 0x18(%rdi), %r12 + movq 0x20(%rdi), %r13 + movq 0x28(%rdi), %r14 + movq 0x30(%rdi), %r15 + xor %rdx,%rdx + mov $1,%rcx + cmp %rax,%rdx + cmove %rcx,%rax + jmp *0x38(%rdi) diff --git a/gnu-efi/x86_64/bootloader/main.efi b/gnu-efi/x86_64/bootloader/main.efi new file mode 100755 index 0000000..7aa8acf Binary files /dev/null and b/gnu-efi/x86_64/bootloader/main.efi differ diff --git a/gnu-efi/x86_64/gnuefi/crt0-efi-x86_64.o b/gnu-efi/x86_64/gnuefi/crt0-efi-x86_64.o new file mode 100644 index 0000000..aec5e7a Binary files /dev/null and b/gnu-efi/x86_64/gnuefi/crt0-efi-x86_64.o differ diff --git a/gnu-efi/x86_64/gnuefi/libgnuefi.a b/gnu-efi/x86_64/gnuefi/libgnuefi.a new file mode 100644 index 0000000..be7d15e Binary files /dev/null and b/gnu-efi/x86_64/gnuefi/libgnuefi.a differ diff --git a/gnu-efi/x86_64/gnuefi/reloc_x86_64.o b/gnu-efi/x86_64/gnuefi/reloc_x86_64.o new file mode 100644 index 0000000..0404787 Binary files /dev/null and b/gnu-efi/x86_64/gnuefi/reloc_x86_64.o differ diff --git a/gnu-efi/x86_64/lib/boxdraw.o b/gnu-efi/x86_64/lib/boxdraw.o new file mode 100644 index 0000000..a75ce63 Binary files /dev/null and b/gnu-efi/x86_64/lib/boxdraw.o differ diff --git a/gnu-efi/x86_64/lib/cmdline.o b/gnu-efi/x86_64/lib/cmdline.o new file mode 100644 index 0000000..92adfbc Binary files /dev/null and b/gnu-efi/x86_64/lib/cmdline.o differ diff --git a/gnu-efi/x86_64/lib/console.o b/gnu-efi/x86_64/lib/console.o new file mode 100644 index 0000000..6ea6be4 Binary files /dev/null and b/gnu-efi/x86_64/lib/console.o differ diff --git a/gnu-efi/x86_64/lib/crc.o b/gnu-efi/x86_64/lib/crc.o new file mode 100644 index 0000000..9213835 Binary files /dev/null and b/gnu-efi/x86_64/lib/crc.o differ diff --git a/gnu-efi/x86_64/lib/data.o b/gnu-efi/x86_64/lib/data.o new file mode 100644 index 0000000..901e42e Binary files /dev/null and b/gnu-efi/x86_64/lib/data.o differ diff --git a/gnu-efi/x86_64/lib/debug.o b/gnu-efi/x86_64/lib/debug.o new file mode 100644 index 0000000..560d0de Binary files /dev/null and b/gnu-efi/x86_64/lib/debug.o differ diff --git a/gnu-efi/x86_64/lib/dpath.o b/gnu-efi/x86_64/lib/dpath.o new file mode 100644 index 0000000..160af87 Binary files /dev/null and b/gnu-efi/x86_64/lib/dpath.o differ diff --git a/gnu-efi/x86_64/lib/error.o b/gnu-efi/x86_64/lib/error.o new file mode 100644 index 0000000..9ba1d9e Binary files /dev/null and b/gnu-efi/x86_64/lib/error.o differ diff --git a/gnu-efi/x86_64/lib/event.o b/gnu-efi/x86_64/lib/event.o new file mode 100644 index 0000000..a7c1eea Binary files /dev/null and b/gnu-efi/x86_64/lib/event.o differ diff --git a/gnu-efi/x86_64/lib/exit.o b/gnu-efi/x86_64/lib/exit.o new file mode 100644 index 0000000..333efe9 Binary files /dev/null and b/gnu-efi/x86_64/lib/exit.o differ diff --git a/gnu-efi/x86_64/lib/guid.o b/gnu-efi/x86_64/lib/guid.o new file mode 100644 index 0000000..f907e1c Binary files /dev/null and b/gnu-efi/x86_64/lib/guid.o differ diff --git a/gnu-efi/x86_64/lib/hand.o b/gnu-efi/x86_64/lib/hand.o new file mode 100644 index 0000000..9c39a58 Binary files /dev/null and b/gnu-efi/x86_64/lib/hand.o differ diff --git a/gnu-efi/x86_64/lib/hw.o b/gnu-efi/x86_64/lib/hw.o new file mode 100644 index 0000000..001ef10 Binary files /dev/null and b/gnu-efi/x86_64/lib/hw.o differ diff --git a/gnu-efi/x86_64/lib/init.o b/gnu-efi/x86_64/lib/init.o new file mode 100644 index 0000000..6c20e90 Binary files /dev/null and b/gnu-efi/x86_64/lib/init.o differ diff --git a/gnu-efi/x86_64/lib/libefi.a b/gnu-efi/x86_64/lib/libefi.a new file mode 100644 index 0000000..b4d8c4e Binary files /dev/null and b/gnu-efi/x86_64/lib/libefi.a differ diff --git a/gnu-efi/x86_64/lib/lock.o b/gnu-efi/x86_64/lib/lock.o new file mode 100644 index 0000000..6134931 Binary files /dev/null and b/gnu-efi/x86_64/lib/lock.o differ diff --git a/gnu-efi/x86_64/lib/misc.o b/gnu-efi/x86_64/lib/misc.o new file mode 100644 index 0000000..e9e46c5 Binary files /dev/null and b/gnu-efi/x86_64/lib/misc.o differ diff --git a/gnu-efi/x86_64/lib/print.o b/gnu-efi/x86_64/lib/print.o new file mode 100644 index 0000000..4d137cf Binary files /dev/null and b/gnu-efi/x86_64/lib/print.o differ diff --git a/gnu-efi/x86_64/lib/runtime/efirtlib.o b/gnu-efi/x86_64/lib/runtime/efirtlib.o new file mode 100644 index 0000000..5a8f188 Binary files /dev/null and b/gnu-efi/x86_64/lib/runtime/efirtlib.o differ diff --git a/gnu-efi/x86_64/lib/runtime/rtdata.o b/gnu-efi/x86_64/lib/runtime/rtdata.o new file mode 100644 index 0000000..f08d3bb Binary files /dev/null and b/gnu-efi/x86_64/lib/runtime/rtdata.o differ diff --git a/gnu-efi/x86_64/lib/runtime/rtlock.o b/gnu-efi/x86_64/lib/runtime/rtlock.o new file mode 100644 index 0000000..9bbcb66 Binary files /dev/null and b/gnu-efi/x86_64/lib/runtime/rtlock.o differ diff --git a/gnu-efi/x86_64/lib/runtime/rtstr.o b/gnu-efi/x86_64/lib/runtime/rtstr.o new file mode 100644 index 0000000..7033c49 Binary files /dev/null and b/gnu-efi/x86_64/lib/runtime/rtstr.o differ diff --git a/gnu-efi/x86_64/lib/runtime/vm.o b/gnu-efi/x86_64/lib/runtime/vm.o new file mode 100644 index 0000000..d607f92 Binary files /dev/null and b/gnu-efi/x86_64/lib/runtime/vm.o differ diff --git a/gnu-efi/x86_64/lib/smbios.o b/gnu-efi/x86_64/lib/smbios.o new file mode 100644 index 0000000..12074e9 Binary files /dev/null and b/gnu-efi/x86_64/lib/smbios.o differ diff --git a/gnu-efi/x86_64/lib/sread.o b/gnu-efi/x86_64/lib/sread.o new file mode 100644 index 0000000..4e76912 Binary files /dev/null and b/gnu-efi/x86_64/lib/sread.o differ diff --git a/gnu-efi/x86_64/lib/str.o b/gnu-efi/x86_64/lib/str.o new file mode 100644 index 0000000..19772a1 Binary files /dev/null and b/gnu-efi/x86_64/lib/str.o differ diff --git a/gnu-efi/x86_64/lib/x86_64/callwrap.o b/gnu-efi/x86_64/lib/x86_64/callwrap.o new file mode 100644 index 0000000..06f24b3 Binary files /dev/null and b/gnu-efi/x86_64/lib/x86_64/callwrap.o differ diff --git a/gnu-efi/x86_64/lib/x86_64/efi_stub.o b/gnu-efi/x86_64/lib/x86_64/efi_stub.o new file mode 100644 index 0000000..7c55e96 Binary files /dev/null and b/gnu-efi/x86_64/lib/x86_64/efi_stub.o differ diff --git a/gnu-efi/x86_64/lib/x86_64/initplat.o b/gnu-efi/x86_64/lib/x86_64/initplat.o new file mode 100644 index 0000000..8052e8f Binary files /dev/null and b/gnu-efi/x86_64/lib/x86_64/initplat.o differ diff --git a/gnu-efi/x86_64/lib/x86_64/math.o b/gnu-efi/x86_64/lib/x86_64/math.o new file mode 100644 index 0000000..07cb4c4 Binary files /dev/null and b/gnu-efi/x86_64/lib/x86_64/math.o differ diff --git a/gnu-efi/x86_64/lib/x86_64/setjmp.o b/gnu-efi/x86_64/lib/x86_64/setjmp.o new file mode 100644 index 0000000..ed60d84 Binary files /dev/null and b/gnu-efi/x86_64/lib/x86_64/setjmp.o differ diff --git a/kernel/Makefile b/kernel/Makefile new file mode 100644 index 0000000..63d9893 --- /dev/null +++ b/kernel/Makefile @@ -0,0 +1,62 @@ + +OSNAME = CustomOS + +GNUEFI = ../gnu-efi +OVMFDIR = ../OVMFbin +LDS = kernel.ld +CC = gcc +LD = ld + +CFLAGS = -ffreestanding -fshort-wchar +LDFLAGS = -T $(LDS) -static -Bsymbolic -nostdlib +OSNAME = CustomOS + +GNUEFI = ../gnu-efi +OVMFDIR = ../OVMFbin +LDS = kernel.ld +CC = gcc +LD = ld + +CFLAGS = -ffreestanding -fshort-wchar +LDFLAGS = -T $(LDS) -static -Bsymbolic -nostdlib + +SRCDIR := src +OBJDIR := lib +BUILDDIR = bin +BOOTEFI := $(GNUEFI)/x86_64/bootloader/main.efi + +rwildcard=$(foreach d,$(wildcard $(1:=/*)),$(call rwildcard,$d,$2) $(filter $(subst *,%,$2),$d)) + +SRC = $(call rwildcard,$(SRCDIR),*.cpp) +OBJS = $(patsubst $(SRCDIR)/%.cpp, $(OBJDIR)/%.o, $(SRC)) +DIRS = $(wildcard $(SRCDIR)/*) + +kernel: $(OBJS) link + +$(OBJDIR)/%.o: $(SRCDIR)/%.cpp + @ echo !==== COMPILING $^ + @ mkdir -p $(@D) + $(CC) $(CFLAGS) -c $^ -o $@ + +link: + @ echo !==== LINKING + @echo $(OBJS) + $(LD) $(LDFLAGS) -o $(BUILDDIR)/kernel.elf $(OBJS) + +setup: + @mkdir $(BUILDDIR) + @mkdir $(SRCDIR) + @mkdir $(OBJDIR) + +buildimg: + dd if=/dev/zero of=$(BUILDDIR)/$(OSNAME).img bs=512 count=93750 + mformat -i $(BUILDDIR)/$(OSNAME).img :: + mmd -i $(BUILDDIR)/$(OSNAME).img ::/EFI + mmd -i $(BUILDDIR)/$(OSNAME).img ::/EFI/BOOT + mcopy -i $(BUILDDIR)/$(OSNAME).img $(BOOTEFI) ::/EFI/BOOT + mcopy -i $(BUILDDIR)/$(OSNAME).img startup.nsh :: + mcopy -i $(BUILDDIR)/$(OSNAME).img $(BUILDDIR)/kernel.elf :: + mcopy -i $(BUILDDIR)/$(OSNAME).img $(BUILDDIR)/zap-light18.psf :: + +run: + qemu-system-x86_64 -drive file=$(BUILDDIR)/$(OSNAME).img -m 256M -cpu qemu64 -drive if=pflash,format=raw,unit=0,file="$(OVMFDIR)/OVMF_CODE-pure-efi.fd",readonly=on -drive if=pflash,format=raw,unit=1,file="$(OVMFDIR)/OVMF_VARS-pure-efi.fd" -net none diff --git a/kernel/bin/CustomOS.img b/kernel/bin/CustomOS.img new file mode 100644 index 0000000..822955f Binary files /dev/null and b/kernel/bin/CustomOS.img differ diff --git a/kernel/bin/kernel.elf b/kernel/bin/kernel.elf new file mode 100755 index 0000000..4615a03 Binary files /dev/null and b/kernel/bin/kernel.elf differ diff --git a/kernel/bin/zap-light18.psf b/kernel/bin/zap-light18.psf new file mode 100644 index 0000000..116d31e Binary files /dev/null and b/kernel/bin/zap-light18.psf differ diff --git a/kernel/git folder/COMMIT_EDITMSG b/kernel/git folder/COMMIT_EDITMSG new file mode 100644 index 0000000..8d00b70 --- /dev/null +++ b/kernel/git folder/COMMIT_EDITMSG @@ -0,0 +1,21 @@ +migrate kernel from C to C++ +# Please enter the commit message for your changes. Lines starting +# with '#' will be ignored, and an empty message aborts the commit. +# +# On branch main +# Your branch is up to date with 'origin/main'. +# +# Changes to be committed: +# modified: Makefile +# modified: bin/CustomOS.img +# modified: bin/kernel.elf +# new file: lib/BasicRenderer.o +# modified: lib/kernel.o +# new file: src/BasicRenderer.cpp +# new file: src/BasicRenderer.h +# new file: src/Framebuffer.h +# new file: src/PSF1Font.h +# deleted: src/kernel.c +# new file: src/kernel.cpp +# new file: src/math.h +# diff --git a/kernel/git folder/FETCH_HEAD b/kernel/git folder/FETCH_HEAD new file mode 100644 index 0000000..016a7bf --- /dev/null +++ b/kernel/git folder/FETCH_HEAD @@ -0,0 +1 @@ +761cc707a175daab8564f4471bf9d0f93f3afab3 branch 'main' of https://github.com/SpookyDervish/kernel diff --git a/kernel/git folder/HEAD b/kernel/git folder/HEAD new file mode 100644 index 0000000..b870d82 --- /dev/null +++ b/kernel/git folder/HEAD @@ -0,0 +1 @@ +ref: refs/heads/main diff --git a/kernel/git folder/ORIG_HEAD b/kernel/git folder/ORIG_HEAD new file mode 100644 index 0000000..2070c02 --- /dev/null +++ b/kernel/git folder/ORIG_HEAD @@ -0,0 +1 @@ +42e87e1d3dbc0a7e79b354179d301887d9cba722 diff --git a/kernel/git folder/config b/kernel/git folder/config new file mode 100644 index 0000000..d6a0061 --- /dev/null +++ b/kernel/git folder/config @@ -0,0 +1,15 @@ +[core] + repositoryformatversion = 0 + filemode = true + bare = false + logallrefupdates = true +[remote "upstream"] + url = https://github.com/Absurdponcho/kernel + fetch = +refs/heads/*:refs/remotes/upstream/* +[branch "main"] + remote = origin + vscode-merge-base = origin/main + merge = refs/heads/main +[remote "origin"] + url = https://github.com/SpookyDervish/kernel.git + fetch = +refs/heads/*:refs/remotes/origin/* diff --git a/kernel/git folder/description b/kernel/git folder/description new file mode 100644 index 0000000..498b267 --- /dev/null +++ b/kernel/git folder/description @@ -0,0 +1 @@ +Unnamed repository; edit this file 'description' to name the repository. diff --git a/kernel/git folder/hooks/applypatch-msg.sample b/kernel/git folder/hooks/applypatch-msg.sample new file mode 100755 index 0000000..a5d7b84 --- /dev/null +++ b/kernel/git folder/hooks/applypatch-msg.sample @@ -0,0 +1,15 @@ +#!/bin/sh +# +# An example hook script to check the commit log message taken by +# applypatch from an e-mail message. +# +# The hook should exit with non-zero status after issuing an +# appropriate message if it wants to stop the commit. The hook is +# allowed to edit the commit message file. +# +# To enable this hook, rename this file to "applypatch-msg". + +. git-sh-setup +commitmsg="$(git rev-parse --git-path hooks/commit-msg)" +test -x "$commitmsg" && exec "$commitmsg" ${1+"$@"} +: diff --git a/kernel/git folder/hooks/commit-msg.sample b/kernel/git folder/hooks/commit-msg.sample new file mode 100755 index 0000000..b58d118 --- /dev/null +++ b/kernel/git folder/hooks/commit-msg.sample @@ -0,0 +1,24 @@ +#!/bin/sh +# +# An example hook script to check the commit log message. +# Called by "git commit" with one argument, the name of the file +# that has the commit message. The hook should exit with non-zero +# status after issuing an appropriate message if it wants to stop the +# commit. The hook is allowed to edit the commit message file. +# +# To enable this hook, rename this file to "commit-msg". + +# Uncomment the below to add a Signed-off-by line to the message. +# Doing this in a hook is a bad idea in general, but the prepare-commit-msg +# hook is more suited to it. +# +# SOB=$(git var GIT_AUTHOR_IDENT | sed -n 's/^\(.*>\).*$/Signed-off-by: \1/p') +# grep -qs "^$SOB" "$1" || echo "$SOB" >> "$1" + +# This example catches duplicate Signed-off-by lines. + +test "" = "$(grep '^Signed-off-by: ' "$1" | + sort | uniq -c | sed -e '/^[ ]*1[ ]/d')" || { + echo >&2 Duplicate Signed-off-by lines. + exit 1 +} diff --git a/kernel/git folder/hooks/fsmonitor-watchman.sample b/kernel/git folder/hooks/fsmonitor-watchman.sample new file mode 100755 index 0000000..23e856f --- /dev/null +++ b/kernel/git folder/hooks/fsmonitor-watchman.sample @@ -0,0 +1,174 @@ +#!/usr/bin/perl + +use strict; +use warnings; +use IPC::Open2; + +# An example hook script to integrate Watchman +# (https://facebook.github.io/watchman/) with git to speed up detecting +# new and modified files. +# +# The hook is passed a version (currently 2) and last update token +# formatted as a string and outputs to stdout a new update token and +# all files that have been modified since the update token. Paths must +# be relative to the root of the working tree and separated by a single NUL. +# +# To enable this hook, rename this file to "query-watchman" and set +# 'git config core.fsmonitor .git/hooks/query-watchman' +# +my ($version, $last_update_token) = @ARGV; + +# Uncomment for debugging +# print STDERR "$0 $version $last_update_token\n"; + +# Check the hook interface version +if ($version ne 2) { + die "Unsupported query-fsmonitor hook version '$version'.\n" . + "Falling back to scanning...\n"; +} + +my $git_work_tree = get_working_dir(); + +my $retry = 1; + +my $json_pkg; +eval { + require JSON::XS; + $json_pkg = "JSON::XS"; + 1; +} or do { + require JSON::PP; + $json_pkg = "JSON::PP"; +}; + +launch_watchman(); + +sub launch_watchman { + my $o = watchman_query(); + if (is_work_tree_watched($o)) { + output_result($o->{clock}, @{$o->{files}}); + } +} + +sub output_result { + my ($clockid, @files) = @_; + + # Uncomment for debugging watchman output + # open (my $fh, ">", ".git/watchman-output.out"); + # binmode $fh, ":utf8"; + # print $fh "$clockid\n@files\n"; + # close $fh; + + binmode STDOUT, ":utf8"; + print $clockid; + print "\0"; + local $, = "\0"; + print @files; +} + +sub watchman_clock { + my $response = qx/watchman clock "$git_work_tree"/; + die "Failed to get clock id on '$git_work_tree'.\n" . + "Falling back to scanning...\n" if $? != 0; + + return $json_pkg->new->utf8->decode($response); +} + +sub watchman_query { + my $pid = open2(\*CHLD_OUT, \*CHLD_IN, 'watchman -j --no-pretty') + or die "open2() failed: $!\n" . + "Falling back to scanning...\n"; + + # In the query expression below we're asking for names of files that + # changed since $last_update_token but not from the .git folder. + # + # To accomplish this, we're using the "since" generator to use the + # recency index to select candidate nodes and "fields" to limit the + # output to file names only. Then we're using the "expression" term to + # further constrain the results. + my $last_update_line = ""; + if (substr($last_update_token, 0, 1) eq "c") { + $last_update_token = "\"$last_update_token\""; + $last_update_line = qq[\n"since": $last_update_token,]; + } + my $query = <<" END"; + ["query", "$git_work_tree", {$last_update_line + "fields": ["name"], + "expression": ["not", ["dirname", ".git"]] + }] + END + + # Uncomment for debugging the watchman query + # open (my $fh, ">", ".git/watchman-query.json"); + # print $fh $query; + # close $fh; + + print CHLD_IN $query; + close CHLD_IN; + my $response = do {local $/; }; + + # Uncomment for debugging the watch response + # open ($fh, ">", ".git/watchman-response.json"); + # print $fh $response; + # close $fh; + + die "Watchman: command returned no output.\n" . + "Falling back to scanning...\n" if $response eq ""; + die "Watchman: command returned invalid output: $response\n" . + "Falling back to scanning...\n" unless $response =~ /^\{/; + + return $json_pkg->new->utf8->decode($response); +} + +sub is_work_tree_watched { + my ($output) = @_; + my $error = $output->{error}; + if ($retry > 0 and $error and $error =~ m/unable to resolve root .* directory (.*) is not watched/) { + $retry--; + my $response = qx/watchman watch "$git_work_tree"/; + die "Failed to make watchman watch '$git_work_tree'.\n" . + "Falling back to scanning...\n" if $? != 0; + $output = $json_pkg->new->utf8->decode($response); + $error = $output->{error}; + die "Watchman: $error.\n" . + "Falling back to scanning...\n" if $error; + + # Uncomment for debugging watchman output + # open (my $fh, ">", ".git/watchman-output.out"); + # close $fh; + + # Watchman will always return all files on the first query so + # return the fast "everything is dirty" flag to git and do the + # Watchman query just to get it over with now so we won't pay + # the cost in git to look up each individual file. + my $o = watchman_clock(); + $error = $output->{error}; + + die "Watchman: $error.\n" . + "Falling back to scanning...\n" if $error; + + output_result($o->{clock}, ("/")); + $last_update_token = $o->{clock}; + + eval { launch_watchman() }; + return 0; + } + + die "Watchman: $error.\n" . + "Falling back to scanning...\n" if $error; + + return 1; +} + +sub get_working_dir { + my $working_dir; + if ($^O =~ 'msys' || $^O =~ 'cygwin') { + $working_dir = Win32::GetCwd(); + $working_dir =~ tr/\\/\//; + } else { + require Cwd; + $working_dir = Cwd::cwd(); + } + + return $working_dir; +} diff --git a/kernel/git folder/hooks/post-update.sample b/kernel/git folder/hooks/post-update.sample new file mode 100755 index 0000000..ec17ec1 --- /dev/null +++ b/kernel/git folder/hooks/post-update.sample @@ -0,0 +1,8 @@ +#!/bin/sh +# +# An example hook script to prepare a packed repository for use over +# dumb transports. +# +# To enable this hook, rename this file to "post-update". + +exec git update-server-info diff --git a/kernel/git folder/hooks/pre-applypatch.sample b/kernel/git folder/hooks/pre-applypatch.sample new file mode 100755 index 0000000..4142082 --- /dev/null +++ b/kernel/git folder/hooks/pre-applypatch.sample @@ -0,0 +1,14 @@ +#!/bin/sh +# +# An example hook script to verify what is about to be committed +# by applypatch from an e-mail message. +# +# The hook should exit with non-zero status after issuing an +# appropriate message if it wants to stop the commit. +# +# To enable this hook, rename this file to "pre-applypatch". + +. git-sh-setup +precommit="$(git rev-parse --git-path hooks/pre-commit)" +test -x "$precommit" && exec "$precommit" ${1+"$@"} +: diff --git a/kernel/git folder/hooks/pre-commit.sample b/kernel/git folder/hooks/pre-commit.sample new file mode 100755 index 0000000..29ed5ee --- /dev/null +++ b/kernel/git folder/hooks/pre-commit.sample @@ -0,0 +1,49 @@ +#!/bin/sh +# +# An example hook script to verify what is about to be committed. +# Called by "git commit" with no arguments. The hook should +# exit with non-zero status after issuing an appropriate message if +# it wants to stop the commit. +# +# To enable this hook, rename this file to "pre-commit". + +if git rev-parse --verify HEAD >/dev/null 2>&1 +then + against=HEAD +else + # Initial commit: diff against an empty tree object + against=$(git hash-object -t tree /dev/null) +fi + +# If you want to allow non-ASCII filenames set this variable to true. +allownonascii=$(git config --type=bool hooks.allownonascii) + +# Redirect output to stderr. +exec 1>&2 + +# Cross platform projects tend to avoid non-ASCII filenames; prevent +# them from being added to the repository. We exploit the fact that the +# printable range starts at the space character and ends with tilde. +if [ "$allownonascii" != "true" ] && + # Note that the use of brackets around a tr range is ok here, (it's + # even required, for portability to Solaris 10's /usr/bin/tr), since + # the square bracket bytes happen to fall in the designated range. + test $(git diff-index --cached --name-only --diff-filter=A -z $against | + LC_ALL=C tr -d '[ -~]\0' | wc -c) != 0 +then + cat <<\EOF +Error: Attempt to add a non-ASCII file name. + +This can cause problems if you want to work with people on other platforms. + +To be portable it is advisable to rename the file. + +If you know what you are doing you can disable this check using: + + git config hooks.allownonascii true +EOF + exit 1 +fi + +# If there are whitespace errors, print the offending file names and fail. +exec git diff-index --check --cached $against -- diff --git a/kernel/git folder/hooks/pre-merge-commit.sample b/kernel/git folder/hooks/pre-merge-commit.sample new file mode 100755 index 0000000..399eab1 --- /dev/null +++ b/kernel/git folder/hooks/pre-merge-commit.sample @@ -0,0 +1,13 @@ +#!/bin/sh +# +# An example hook script to verify what is about to be committed. +# Called by "git merge" with no arguments. The hook should +# exit with non-zero status after issuing an appropriate message to +# stderr if it wants to stop the merge commit. +# +# To enable this hook, rename this file to "pre-merge-commit". + +. git-sh-setup +test -x "$GIT_DIR/hooks/pre-commit" && + exec "$GIT_DIR/hooks/pre-commit" +: diff --git a/kernel/git folder/hooks/pre-push.sample b/kernel/git folder/hooks/pre-push.sample new file mode 100755 index 0000000..4ce688d --- /dev/null +++ b/kernel/git folder/hooks/pre-push.sample @@ -0,0 +1,53 @@ +#!/bin/sh + +# An example hook script to verify what is about to be pushed. Called by "git +# push" after it has checked the remote status, but before anything has been +# pushed. If this script exits with a non-zero status nothing will be pushed. +# +# This hook is called with the following parameters: +# +# $1 -- Name of the remote to which the push is being done +# $2 -- URL to which the push is being done +# +# If pushing without using a named remote those arguments will be equal. +# +# Information about the commits which are being pushed is supplied as lines to +# the standard input in the form: +# +# +# +# This sample shows how to prevent push of commits where the log message starts +# with "WIP" (work in progress). + +remote="$1" +url="$2" + +zero=$(git hash-object --stdin &2 "Found WIP commit in $local_ref, not pushing" + exit 1 + fi + fi +done + +exit 0 diff --git a/kernel/git folder/hooks/pre-rebase.sample b/kernel/git folder/hooks/pre-rebase.sample new file mode 100755 index 0000000..6cbef5c --- /dev/null +++ b/kernel/git folder/hooks/pre-rebase.sample @@ -0,0 +1,169 @@ +#!/bin/sh +# +# Copyright (c) 2006, 2008 Junio C Hamano +# +# The "pre-rebase" hook is run just before "git rebase" starts doing +# its job, and can prevent the command from running by exiting with +# non-zero status. +# +# The hook is called with the following parameters: +# +# $1 -- the upstream the series was forked from. +# $2 -- the branch being rebased (or empty when rebasing the current branch). +# +# This sample shows how to prevent topic branches that are already +# merged to 'next' branch from getting rebased, because allowing it +# would result in rebasing already published history. + +publish=next +basebranch="$1" +if test "$#" = 2 +then + topic="refs/heads/$2" +else + topic=`git symbolic-ref HEAD` || + exit 0 ;# we do not interrupt rebasing detached HEAD +fi + +case "$topic" in +refs/heads/??/*) + ;; +*) + exit 0 ;# we do not interrupt others. + ;; +esac + +# Now we are dealing with a topic branch being rebased +# on top of master. Is it OK to rebase it? + +# Does the topic really exist? +git show-ref -q "$topic" || { + echo >&2 "No such branch $topic" + exit 1 +} + +# Is topic fully merged to master? +not_in_master=`git rev-list --pretty=oneline ^master "$topic"` +if test -z "$not_in_master" +then + echo >&2 "$topic is fully merged to master; better remove it." + exit 1 ;# we could allow it, but there is no point. +fi + +# Is topic ever merged to next? If so you should not be rebasing it. +only_next_1=`git rev-list ^master "^$topic" ${publish} | sort` +only_next_2=`git rev-list ^master ${publish} | sort` +if test "$only_next_1" = "$only_next_2" +then + not_in_topic=`git rev-list "^$topic" master` + if test -z "$not_in_topic" + then + echo >&2 "$topic is already up to date with master" + exit 1 ;# we could allow it, but there is no point. + else + exit 0 + fi +else + not_in_next=`git rev-list --pretty=oneline ^${publish} "$topic"` + /usr/bin/perl -e ' + my $topic = $ARGV[0]; + my $msg = "* $topic has commits already merged to public branch:\n"; + my (%not_in_next) = map { + /^([0-9a-f]+) /; + ($1 => 1); + } split(/\n/, $ARGV[1]); + for my $elem (map { + /^([0-9a-f]+) (.*)$/; + [$1 => $2]; + } split(/\n/, $ARGV[2])) { + if (!exists $not_in_next{$elem->[0]}) { + if ($msg) { + print STDERR $msg; + undef $msg; + } + print STDERR " $elem->[1]\n"; + } + } + ' "$topic" "$not_in_next" "$not_in_master" + exit 1 +fi + +<<\DOC_END + +This sample hook safeguards topic branches that have been +published from being rewound. + +The workflow assumed here is: + + * Once a topic branch forks from "master", "master" is never + merged into it again (either directly or indirectly). + + * Once a topic branch is fully cooked and merged into "master", + it is deleted. If you need to build on top of it to correct + earlier mistakes, a new topic branch is created by forking at + the tip of the "master". This is not strictly necessary, but + it makes it easier to keep your history simple. + + * Whenever you need to test or publish your changes to topic + branches, merge them into "next" branch. + +The script, being an example, hardcodes the publish branch name +to be "next", but it is trivial to make it configurable via +$GIT_DIR/config mechanism. + +With this workflow, you would want to know: + +(1) ... if a topic branch has ever been merged to "next". Young + topic branches can have stupid mistakes you would rather + clean up before publishing, and things that have not been + merged into other branches can be easily rebased without + affecting other people. But once it is published, you would + not want to rewind it. + +(2) ... if a topic branch has been fully merged to "master". + Then you can delete it. More importantly, you should not + build on top of it -- other people may already want to + change things related to the topic as patches against your + "master", so if you need further changes, it is better to + fork the topic (perhaps with the same name) afresh from the + tip of "master". + +Let's look at this example: + + o---o---o---o---o---o---o---o---o---o "next" + / / / / + / a---a---b A / / + / / / / + / / c---c---c---c B / + / / / \ / + / / / b---b C \ / + / / / / \ / + ---o---o---o---o---o---o---o---o---o---o---o "master" + + +A, B and C are topic branches. + + * A has one fix since it was merged up to "next". + + * B has finished. It has been fully merged up to "master" and "next", + and is ready to be deleted. + + * C has not merged to "next" at all. + +We would want to allow C to be rebased, refuse A, and encourage +B to be deleted. + +To compute (1): + + git rev-list ^master ^topic next + git rev-list ^master next + + if these match, topic has not merged in next at all. + +To compute (2): + + git rev-list master..topic + + if this is empty, it is fully merged to "master". + +DOC_END diff --git a/kernel/git folder/hooks/pre-receive.sample b/kernel/git folder/hooks/pre-receive.sample new file mode 100755 index 0000000..a1fd29e --- /dev/null +++ b/kernel/git folder/hooks/pre-receive.sample @@ -0,0 +1,24 @@ +#!/bin/sh +# +# An example hook script to make use of push options. +# The example simply echoes all push options that start with 'echoback=' +# and rejects all pushes when the "reject" push option is used. +# +# To enable this hook, rename this file to "pre-receive". + +if test -n "$GIT_PUSH_OPTION_COUNT" +then + i=0 + while test "$i" -lt "$GIT_PUSH_OPTION_COUNT" + do + eval "value=\$GIT_PUSH_OPTION_$i" + case "$value" in + echoback=*) + echo "echo from the pre-receive-hook: ${value#*=}" >&2 + ;; + reject) + exit 1 + esac + i=$((i + 1)) + done +fi diff --git a/kernel/git folder/hooks/prepare-commit-msg.sample b/kernel/git folder/hooks/prepare-commit-msg.sample new file mode 100755 index 0000000..10fa14c --- /dev/null +++ b/kernel/git folder/hooks/prepare-commit-msg.sample @@ -0,0 +1,42 @@ +#!/bin/sh +# +# An example hook script to prepare the commit log message. +# Called by "git commit" with the name of the file that has the +# commit message, followed by the description of the commit +# message's source. The hook's purpose is to edit the commit +# message file. If the hook fails with a non-zero status, +# the commit is aborted. +# +# To enable this hook, rename this file to "prepare-commit-msg". + +# This hook includes three examples. The first one removes the +# "# Please enter the commit message..." help message. +# +# The second includes the output of "git diff --name-status -r" +# into the message, just before the "git status" output. It is +# commented because it doesn't cope with --amend or with squashed +# commits. +# +# The third example adds a Signed-off-by line to the message, that can +# still be edited. This is rarely a good idea. + +COMMIT_MSG_FILE=$1 +COMMIT_SOURCE=$2 +SHA1=$3 + +/usr/bin/perl -i.bak -ne 'print unless(m/^. Please enter the commit message/..m/^#$/)' "$COMMIT_MSG_FILE" + +# case "$COMMIT_SOURCE,$SHA1" in +# ,|template,) +# /usr/bin/perl -i.bak -pe ' +# print "\n" . `git diff --cached --name-status -r` +# if /^#/ && $first++ == 0' "$COMMIT_MSG_FILE" ;; +# *) ;; +# esac + +# SOB=$(git var GIT_COMMITTER_IDENT | sed -n 's/^\(.*>\).*$/Signed-off-by: \1/p') +# git interpret-trailers --in-place --trailer "$SOB" "$COMMIT_MSG_FILE" +# if test -z "$COMMIT_SOURCE" +# then +# /usr/bin/perl -i.bak -pe 'print "\n" if !$first_line++' "$COMMIT_MSG_FILE" +# fi diff --git a/kernel/git folder/hooks/push-to-checkout.sample b/kernel/git folder/hooks/push-to-checkout.sample new file mode 100755 index 0000000..af5a0c0 --- /dev/null +++ b/kernel/git folder/hooks/push-to-checkout.sample @@ -0,0 +1,78 @@ +#!/bin/sh + +# An example hook script to update a checked-out tree on a git push. +# +# This hook is invoked by git-receive-pack(1) when it reacts to git +# push and updates reference(s) in its repository, and when the push +# tries to update the branch that is currently checked out and the +# receive.denyCurrentBranch configuration variable is set to +# updateInstead. +# +# By default, such a push is refused if the working tree and the index +# of the remote repository has any difference from the currently +# checked out commit; when both the working tree and the index match +# the current commit, they are updated to match the newly pushed tip +# of the branch. This hook is to be used to override the default +# behaviour; however the code below reimplements the default behaviour +# as a starting point for convenient modification. +# +# The hook receives the commit with which the tip of the current +# branch is going to be updated: +commit=$1 + +# It can exit with a non-zero status to refuse the push (when it does +# so, it must not modify the index or the working tree). +die () { + echo >&2 "$*" + exit 1 +} + +# Or it can make any necessary changes to the working tree and to the +# index to bring them to the desired state when the tip of the current +# branch is updated to the new commit, and exit with a zero status. +# +# For example, the hook can simply run git read-tree -u -m HEAD "$1" +# in order to emulate git fetch that is run in the reverse direction +# with git push, as the two-tree form of git read-tree -u -m is +# essentially the same as git switch or git checkout that switches +# branches while keeping the local changes in the working tree that do +# not interfere with the difference between the branches. + +# The below is a more-or-less exact translation to shell of the C code +# for the default behaviour for git's push-to-checkout hook defined in +# the push_to_deploy() function in builtin/receive-pack.c. +# +# Note that the hook will be executed from the repository directory, +# not from the working tree, so if you want to perform operations on +# the working tree, you will have to adapt your code accordingly, e.g. +# by adding "cd .." or using relative paths. + +if ! git update-index -q --ignore-submodules --refresh +then + die "Up-to-date check failed" +fi + +if ! git diff-files --quiet --ignore-submodules -- +then + die "Working directory has unstaged changes" +fi + +# This is a rough translation of: +# +# head_has_history() ? "HEAD" : EMPTY_TREE_SHA1_HEX +if git cat-file -e HEAD 2>/dev/null +then + head=HEAD +else + head=$(git hash-object -t tree --stdin &2 + exit 1 +} + +unset GIT_DIR GIT_WORK_TREE +cd "$worktree" && + +if grep -q "^diff --git " "$1" +then + validate_patch "$1" +else + validate_cover_letter "$1" +fi && + +if test "$GIT_SENDEMAIL_FILE_COUNTER" = "$GIT_SENDEMAIL_FILE_TOTAL" +then + git config --unset-all sendemail.validateWorktree && + trap 'git worktree remove -ff "$worktree"' EXIT && + validate_series +fi diff --git a/kernel/git folder/hooks/update.sample b/kernel/git folder/hooks/update.sample new file mode 100755 index 0000000..c4d426b --- /dev/null +++ b/kernel/git folder/hooks/update.sample @@ -0,0 +1,128 @@ +#!/bin/sh +# +# An example hook script to block unannotated tags from entering. +# Called by "git receive-pack" with arguments: refname sha1-old sha1-new +# +# To enable this hook, rename this file to "update". +# +# Config +# ------ +# hooks.allowunannotated +# This boolean sets whether unannotated tags will be allowed into the +# repository. By default they won't be. +# hooks.allowdeletetag +# This boolean sets whether deleting tags will be allowed in the +# repository. By default they won't be. +# hooks.allowmodifytag +# This boolean sets whether a tag may be modified after creation. By default +# it won't be. +# hooks.allowdeletebranch +# This boolean sets whether deleting branches will be allowed in the +# repository. By default they won't be. +# hooks.denycreatebranch +# This boolean sets whether remotely creating branches will be denied +# in the repository. By default this is allowed. +# + +# --- Command line +refname="$1" +oldrev="$2" +newrev="$3" + +# --- Safety check +if [ -z "$GIT_DIR" ]; then + echo "Don't run this script from the command line." >&2 + echo " (if you want, you could supply GIT_DIR then run" >&2 + echo " $0 )" >&2 + exit 1 +fi + +if [ -z "$refname" -o -z "$oldrev" -o -z "$newrev" ]; then + echo "usage: $0 " >&2 + exit 1 +fi + +# --- Config +allowunannotated=$(git config --type=bool hooks.allowunannotated) +allowdeletebranch=$(git config --type=bool hooks.allowdeletebranch) +denycreatebranch=$(git config --type=bool hooks.denycreatebranch) +allowdeletetag=$(git config --type=bool hooks.allowdeletetag) +allowmodifytag=$(git config --type=bool hooks.allowmodifytag) + +# check for no description +projectdesc=$(sed -e '1q' "$GIT_DIR/description") +case "$projectdesc" in +"Unnamed repository"* | "") + echo "*** Project description file hasn't been set" >&2 + exit 1 + ;; +esac + +# --- Check types +# if $newrev is 0000...0000, it's a commit to delete a ref. +zero=$(git hash-object --stdin &2 + echo "*** Use 'git tag [ -a | -s ]' for tags you want to propagate." >&2 + exit 1 + fi + ;; + refs/tags/*,delete) + # delete tag + if [ "$allowdeletetag" != "true" ]; then + echo "*** Deleting a tag is not allowed in this repository" >&2 + exit 1 + fi + ;; + refs/tags/*,tag) + # annotated tag + if [ "$allowmodifytag" != "true" ] && git rev-parse $refname > /dev/null 2>&1 + then + echo "*** Tag '$refname' already exists." >&2 + echo "*** Modifying a tag is not allowed in this repository." >&2 + exit 1 + fi + ;; + refs/heads/*,commit) + # branch + if [ "$oldrev" = "$zero" -a "$denycreatebranch" = "true" ]; then + echo "*** Creating a branch is not allowed in this repository" >&2 + exit 1 + fi + ;; + refs/heads/*,delete) + # delete branch + if [ "$allowdeletebranch" != "true" ]; then + echo "*** Deleting a branch is not allowed in this repository" >&2 + exit 1 + fi + ;; + refs/remotes/*,commit) + # tracking branch + ;; + refs/remotes/*,delete) + # delete tracking branch + if [ "$allowdeletebranch" != "true" ]; then + echo "*** Deleting a tracking branch is not allowed in this repository" >&2 + exit 1 + fi + ;; + *) + # Anything else (is there anything else?) + echo "*** Update hook: unknown type of update to ref $refname of type $newrev_type" >&2 + exit 1 + ;; +esac + +# --- Finished +exit 0 diff --git a/kernel/git folder/index b/kernel/git folder/index new file mode 100644 index 0000000..c2369e5 Binary files /dev/null and b/kernel/git folder/index differ diff --git a/kernel/git folder/info/exclude b/kernel/git folder/info/exclude new file mode 100644 index 0000000..a5196d1 --- /dev/null +++ b/kernel/git folder/info/exclude @@ -0,0 +1,6 @@ +# git ls-files --others --exclude-from=.git/info/exclude +# Lines that start with '#' are comments. +# For a project mostly in C, the following would be a good set of +# exclude patterns (uncomment them if you want to use them): +# *.[oa] +# *~ diff --git a/kernel/git folder/logs/HEAD b/kernel/git folder/logs/HEAD new file mode 100644 index 0000000..9280ca6 --- /dev/null +++ b/kernel/git folder/logs/HEAD @@ -0,0 +1,9 @@ +0000000000000000000000000000000000000000 24761e3a8c04bdd94bf75277ea352e7ffaac417e SpookyDervish 1769496478 +1100 clone: from https://github.com/Absurdponcho/kernel +24761e3a8c04bdd94bf75277ea352e7ffaac417e 95debf8491c17eb14e8093e103900020d9db0281 SpookyDervish 1769498273 +1100 commit: build +95debf8491c17eb14e8093e103900020d9db0281 492176b1e88da6ad3c213cc0677fec70683199ae SpookyDervish 1769499973 +1100 commit: kernel elf +492176b1e88da6ad3c213cc0677fec70683199ae 18d8068a5abc7ca043b68550a471c28558b83c48 SpookyDervish 1769502744 +1100 commit: make sure kernel header is correct +18d8068a5abc7ca043b68550a471c28558b83c48 146e4552fa712a60b2c9e0384710266ee86a8046 SpookyDervish 1769503647 +1100 commit: load kernel with bootloader +146e4552fa712a60b2c9e0384710266ee86a8046 d2a9c820ebd7dd73c699c4b83793ce43fd2ea9b1 SpookyDervish 1769508272 +1100 commit: pass framebuffer to kernel +d2a9c820ebd7dd73c699c4b83793ce43fd2ea9b1 1d03658a1126516f90dfb3ccd1007da045fe99dc SpookyDervish 1769509895 +1100 commit: load psf1 font +1d03658a1126516f90dfb3ccd1007da045fe99dc 761cc707a175daab8564f4471bf9d0f93f3afab3 SpookyDervish 1769544073 +1100 commit: printing strings +761cc707a175daab8564f4471bf9d0f93f3afab3 42e87e1d3dbc0a7e79b354179d301887d9cba722 SpookyDervish 1769551672 +1100 commit: migrate kernel from C to C++ diff --git a/kernel/git folder/logs/refs/heads/main b/kernel/git folder/logs/refs/heads/main new file mode 100644 index 0000000..9280ca6 --- /dev/null +++ b/kernel/git folder/logs/refs/heads/main @@ -0,0 +1,9 @@ +0000000000000000000000000000000000000000 24761e3a8c04bdd94bf75277ea352e7ffaac417e SpookyDervish 1769496478 +1100 clone: from https://github.com/Absurdponcho/kernel +24761e3a8c04bdd94bf75277ea352e7ffaac417e 95debf8491c17eb14e8093e103900020d9db0281 SpookyDervish 1769498273 +1100 commit: build +95debf8491c17eb14e8093e103900020d9db0281 492176b1e88da6ad3c213cc0677fec70683199ae SpookyDervish 1769499973 +1100 commit: kernel elf +492176b1e88da6ad3c213cc0677fec70683199ae 18d8068a5abc7ca043b68550a471c28558b83c48 SpookyDervish 1769502744 +1100 commit: make sure kernel header is correct +18d8068a5abc7ca043b68550a471c28558b83c48 146e4552fa712a60b2c9e0384710266ee86a8046 SpookyDervish 1769503647 +1100 commit: load kernel with bootloader +146e4552fa712a60b2c9e0384710266ee86a8046 d2a9c820ebd7dd73c699c4b83793ce43fd2ea9b1 SpookyDervish 1769508272 +1100 commit: pass framebuffer to kernel +d2a9c820ebd7dd73c699c4b83793ce43fd2ea9b1 1d03658a1126516f90dfb3ccd1007da045fe99dc SpookyDervish 1769509895 +1100 commit: load psf1 font +1d03658a1126516f90dfb3ccd1007da045fe99dc 761cc707a175daab8564f4471bf9d0f93f3afab3 SpookyDervish 1769544073 +1100 commit: printing strings +761cc707a175daab8564f4471bf9d0f93f3afab3 42e87e1d3dbc0a7e79b354179d301887d9cba722 SpookyDervish 1769551672 +1100 commit: migrate kernel from C to C++ diff --git a/kernel/git folder/logs/refs/remotes/origin/HEAD b/kernel/git folder/logs/refs/remotes/origin/HEAD new file mode 100644 index 0000000..eea2dad --- /dev/null +++ b/kernel/git folder/logs/refs/remotes/origin/HEAD @@ -0,0 +1 @@ +0000000000000000000000000000000000000000 18d8068a5abc7ca043b68550a471c28558b83c48 SpookyDervish 1769502760 +1100 fetch diff --git a/kernel/git folder/logs/refs/remotes/origin/main b/kernel/git folder/logs/refs/remotes/origin/main new file mode 100644 index 0000000..4c3af7c --- /dev/null +++ b/kernel/git folder/logs/refs/remotes/origin/main @@ -0,0 +1,7 @@ +0000000000000000000000000000000000000000 24761e3a8c04bdd94bf75277ea352e7ffaac417e SpookyDervish 1769502757 +1100 fetch origin main: storing head +24761e3a8c04bdd94bf75277ea352e7ffaac417e 18d8068a5abc7ca043b68550a471c28558b83c48 SpookyDervish 1769502759 +1100 update by push +18d8068a5abc7ca043b68550a471c28558b83c48 146e4552fa712a60b2c9e0384710266ee86a8046 SpookyDervish 1769503671 +1100 update by push +146e4552fa712a60b2c9e0384710266ee86a8046 d2a9c820ebd7dd73c699c4b83793ce43fd2ea9b1 SpookyDervish 1769508285 +1100 update by push +d2a9c820ebd7dd73c699c4b83793ce43fd2ea9b1 1d03658a1126516f90dfb3ccd1007da045fe99dc SpookyDervish 1769509907 +1100 update by push +1d03658a1126516f90dfb3ccd1007da045fe99dc 761cc707a175daab8564f4471bf9d0f93f3afab3 SpookyDervish 1769544081 +1100 update by push +761cc707a175daab8564f4471bf9d0f93f3afab3 42e87e1d3dbc0a7e79b354179d301887d9cba722 SpookyDervish 1769551682 +1100 update by push diff --git a/kernel/git folder/logs/refs/remotes/upstream/HEAD b/kernel/git folder/logs/refs/remotes/upstream/HEAD new file mode 100644 index 0000000..017b0ec --- /dev/null +++ b/kernel/git folder/logs/refs/remotes/upstream/HEAD @@ -0,0 +1,2 @@ +0000000000000000000000000000000000000000 24761e3a8c04bdd94bf75277ea352e7ffaac417e SpookyDervish 1769496478 +1100 clone: from https://github.com/Absurdponcho/kernel +0000000000000000000000000000000000000000 0000000000000000000000000000000000000000 Nathaniel 1769502756 +1100 remote: renamed refs/remotes/origin/HEAD to refs/remotes/upstream/HEAD diff --git a/kernel/git folder/objects/03/b25e66f7e4066296b1d701f75bb3983a1f0f8c b/kernel/git folder/objects/03/b25e66f7e4066296b1d701f75bb3983a1f0f8c new file mode 100644 index 0000000..b99955e Binary files /dev/null and b/kernel/git folder/objects/03/b25e66f7e4066296b1d701f75bb3983a1f0f8c differ diff --git a/kernel/git folder/objects/06/b55afd5bb383e7cdbf9f433bd7364e756c58e1 b/kernel/git folder/objects/06/b55afd5bb383e7cdbf9f433bd7364e756c58e1 new file mode 100644 index 0000000..9f1c05e Binary files /dev/null and b/kernel/git folder/objects/06/b55afd5bb383e7cdbf9f433bd7364e756c58e1 differ diff --git a/kernel/git folder/objects/08/9ce954e474f55fb68b64d21b8fbe05d66bc618 b/kernel/git folder/objects/08/9ce954e474f55fb68b64d21b8fbe05d66bc618 new file mode 100644 index 0000000..382d205 Binary files /dev/null and b/kernel/git folder/objects/08/9ce954e474f55fb68b64d21b8fbe05d66bc618 differ diff --git a/kernel/git folder/objects/09/496617af45725030563de118dd60a22eb1a705 b/kernel/git folder/objects/09/496617af45725030563de118dd60a22eb1a705 new file mode 100644 index 0000000..5ee0471 Binary files /dev/null and b/kernel/git folder/objects/09/496617af45725030563de118dd60a22eb1a705 differ diff --git a/kernel/git folder/objects/0b/d7db346b8ad92b3082656a899133d4583a9314 b/kernel/git folder/objects/0b/d7db346b8ad92b3082656a899133d4583a9314 new file mode 100644 index 0000000..7fe37e5 Binary files /dev/null and b/kernel/git folder/objects/0b/d7db346b8ad92b3082656a899133d4583a9314 differ diff --git a/kernel/git folder/objects/0f/2fc702cd6c354daa675a4b005871e2cb0b5848 b/kernel/git folder/objects/0f/2fc702cd6c354daa675a4b005871e2cb0b5848 new file mode 100644 index 0000000..169c3c2 Binary files /dev/null and b/kernel/git folder/objects/0f/2fc702cd6c354daa675a4b005871e2cb0b5848 differ diff --git a/kernel/git folder/objects/11/6d31e499ea39bd659fe320e8a2a30805a90e01 b/kernel/git folder/objects/11/6d31e499ea39bd659fe320e8a2a30805a90e01 new file mode 100644 index 0000000..6a17701 Binary files /dev/null and b/kernel/git folder/objects/11/6d31e499ea39bd659fe320e8a2a30805a90e01 differ diff --git a/kernel/git folder/objects/14/6e4552fa712a60b2c9e0384710266ee86a8046 b/kernel/git folder/objects/14/6e4552fa712a60b2c9e0384710266ee86a8046 new file mode 100644 index 0000000..ac94f59 Binary files /dev/null and b/kernel/git folder/objects/14/6e4552fa712a60b2c9e0384710266ee86a8046 differ diff --git a/kernel/git folder/objects/15/cc6149c26fa49dc9a590a3ecb8935ec0eeea91 b/kernel/git folder/objects/15/cc6149c26fa49dc9a590a3ecb8935ec0eeea91 new file mode 100644 index 0000000..7c53faa Binary files /dev/null and b/kernel/git folder/objects/15/cc6149c26fa49dc9a590a3ecb8935ec0eeea91 differ diff --git a/kernel/git folder/objects/18/d8068a5abc7ca043b68550a471c28558b83c48 b/kernel/git folder/objects/18/d8068a5abc7ca043b68550a471c28558b83c48 new file mode 100644 index 0000000..5eadb2b Binary files /dev/null and b/kernel/git folder/objects/18/d8068a5abc7ca043b68550a471c28558b83c48 differ diff --git a/kernel/git folder/objects/1a/2c25f0941ee6d3b3d20a41afa506d012c27420 b/kernel/git folder/objects/1a/2c25f0941ee6d3b3d20a41afa506d012c27420 new file mode 100644 index 0000000..8de3eb1 Binary files /dev/null and b/kernel/git folder/objects/1a/2c25f0941ee6d3b3d20a41afa506d012c27420 differ diff --git a/kernel/git folder/objects/1d/03658a1126516f90dfb3ccd1007da045fe99dc b/kernel/git folder/objects/1d/03658a1126516f90dfb3ccd1007da045fe99dc new file mode 100644 index 0000000..17d86f1 Binary files /dev/null and b/kernel/git folder/objects/1d/03658a1126516f90dfb3ccd1007da045fe99dc differ diff --git a/kernel/git folder/objects/1f/9c8437a37dfc9cd95e5c913386f66ad9537880 b/kernel/git folder/objects/1f/9c8437a37dfc9cd95e5c913386f66ad9537880 new file mode 100644 index 0000000..5e22191 Binary files /dev/null and b/kernel/git folder/objects/1f/9c8437a37dfc9cd95e5c913386f66ad9537880 differ diff --git a/kernel/git folder/objects/20/f839ef03dc6af5f7d428837ea3fd6120afdae7 b/kernel/git folder/objects/20/f839ef03dc6af5f7d428837ea3fd6120afdae7 new file mode 100644 index 0000000..c79613b Binary files /dev/null and b/kernel/git folder/objects/20/f839ef03dc6af5f7d428837ea3fd6120afdae7 differ diff --git a/kernel/git folder/objects/22/ae5b0650a838b279754bd73781ddca35fc6c90 b/kernel/git folder/objects/22/ae5b0650a838b279754bd73781ddca35fc6c90 new file mode 100644 index 0000000..fd000dd Binary files /dev/null and b/kernel/git folder/objects/22/ae5b0650a838b279754bd73781ddca35fc6c90 differ diff --git a/kernel/git folder/objects/24/7ff92ab344b8e3c392558e05dcd006d5e35585 b/kernel/git folder/objects/24/7ff92ab344b8e3c392558e05dcd006d5e35585 new file mode 100644 index 0000000..f707276 Binary files /dev/null and b/kernel/git folder/objects/24/7ff92ab344b8e3c392558e05dcd006d5e35585 differ diff --git a/kernel/git folder/objects/29/ceea7da59995781511fa9527f57ad251623807 b/kernel/git folder/objects/29/ceea7da59995781511fa9527f57ad251623807 new file mode 100644 index 0000000..8f59bad Binary files /dev/null and b/kernel/git folder/objects/29/ceea7da59995781511fa9527f57ad251623807 differ diff --git a/kernel/git folder/objects/30/6e52a4d40b11237bc222e8148f935149c9a7a2 b/kernel/git folder/objects/30/6e52a4d40b11237bc222e8148f935149c9a7a2 new file mode 100644 index 0000000..dc9348e Binary files /dev/null and b/kernel/git folder/objects/30/6e52a4d40b11237bc222e8148f935149c9a7a2 differ diff --git a/kernel/git folder/objects/34/23ff4b73823f1c7761d6eaa380a3a0908f51bc b/kernel/git folder/objects/34/23ff4b73823f1c7761d6eaa380a3a0908f51bc new file mode 100644 index 0000000..25d595f Binary files /dev/null and b/kernel/git folder/objects/34/23ff4b73823f1c7761d6eaa380a3a0908f51bc differ diff --git a/kernel/git folder/objects/35/8cc8eccbac664255d615ec1e4e5f3f677257d6 b/kernel/git folder/objects/35/8cc8eccbac664255d615ec1e4e5f3f677257d6 new file mode 100644 index 0000000..1caa463 Binary files /dev/null and b/kernel/git folder/objects/35/8cc8eccbac664255d615ec1e4e5f3f677257d6 differ diff --git a/kernel/git folder/objects/35/da0e763313811c324ed2d850029287d6c02e9a b/kernel/git folder/objects/35/da0e763313811c324ed2d850029287d6c02e9a new file mode 100644 index 0000000..cf178f5 Binary files /dev/null and b/kernel/git folder/objects/35/da0e763313811c324ed2d850029287d6c02e9a differ diff --git a/kernel/git folder/objects/37/2e4094c8411a6e4c79185113d61de001e05bc2 b/kernel/git folder/objects/37/2e4094c8411a6e4c79185113d61de001e05bc2 new file mode 100644 index 0000000..8fa6e64 Binary files /dev/null and b/kernel/git folder/objects/37/2e4094c8411a6e4c79185113d61de001e05bc2 differ diff --git a/kernel/git folder/objects/3b/95efa96156d5dd8d302e01f79e86995d3264a6 b/kernel/git folder/objects/3b/95efa96156d5dd8d302e01f79e86995d3264a6 new file mode 100644 index 0000000..02a1f8e Binary files /dev/null and b/kernel/git folder/objects/3b/95efa96156d5dd8d302e01f79e86995d3264a6 differ diff --git a/kernel/git folder/objects/3e/24b1785677167c263b0a0308ee486ecf7f2211 b/kernel/git folder/objects/3e/24b1785677167c263b0a0308ee486ecf7f2211 new file mode 100644 index 0000000..eadda59 --- /dev/null +++ b/kernel/git folder/objects/3e/24b1785677167c263b0a0308ee486ecf7f2211 @@ -0,0 +1 @@ +x+)JMU042d040031Qp.-.Mgx[G&Ί;d>5BvjQ^j^jNC O/bxl'ԴݜC 4\'3_YMXŢ+>1 \ No newline at end of file diff --git a/kernel/git folder/objects/42/e87e1d3dbc0a7e79b354179d301887d9cba722 b/kernel/git folder/objects/42/e87e1d3dbc0a7e79b354179d301887d9cba722 new file mode 100644 index 0000000..1c03d69 Binary files /dev/null and b/kernel/git folder/objects/42/e87e1d3dbc0a7e79b354179d301887d9cba722 differ diff --git a/kernel/git folder/objects/46/15a03771abbd32a57a17fb6967cdbac1f6fd50 b/kernel/git folder/objects/46/15a03771abbd32a57a17fb6967cdbac1f6fd50 new file mode 100644 index 0000000..923de82 Binary files /dev/null and b/kernel/git folder/objects/46/15a03771abbd32a57a17fb6967cdbac1f6fd50 differ diff --git a/kernel/git folder/objects/49/2176b1e88da6ad3c213cc0677fec70683199ae b/kernel/git folder/objects/49/2176b1e88da6ad3c213cc0677fec70683199ae new file mode 100644 index 0000000..c730313 Binary files /dev/null and b/kernel/git folder/objects/49/2176b1e88da6ad3c213cc0677fec70683199ae differ diff --git a/kernel/git folder/objects/4a/7b5bed812bea99c49a359920ff2076a13647e8 b/kernel/git folder/objects/4a/7b5bed812bea99c49a359920ff2076a13647e8 new file mode 100644 index 0000000..2bdd0e3 Binary files /dev/null and b/kernel/git folder/objects/4a/7b5bed812bea99c49a359920ff2076a13647e8 differ diff --git a/kernel/git folder/objects/58/b4bb6d16da3b33761f7724fb30fbc569f3aa22 b/kernel/git folder/objects/58/b4bb6d16da3b33761f7724fb30fbc569f3aa22 new file mode 100644 index 0000000..578636e --- /dev/null +++ b/kernel/git folder/objects/58/b4bb6d16da3b33761f7724fb30fbc569f3aa22 @@ -0,0 +1 @@ +x+)JMU027f040031QMNMIePeÓBX\`8@!)3NecEXX53;JPSRsrR_vnym3cRALb7΃Ƈeg,5˝zTFP#JKT Cwǘ|soG =[{'bIqQ2C|{VwOVXY84GM ԄĢ NjdCw:Oeq \ No newline at end of file diff --git a/kernel/git folder/objects/5d/1f84ef4441b77b3addc9783a3aa8c29c19ec74 b/kernel/git folder/objects/5d/1f84ef4441b77b3addc9783a3aa8c29c19ec74 new file mode 100644 index 0000000..493d899 Binary files /dev/null and b/kernel/git folder/objects/5d/1f84ef4441b77b3addc9783a3aa8c29c19ec74 differ diff --git a/kernel/git folder/objects/5e/d6b40973a5f1b3b59759619a5ec452379beb09 b/kernel/git folder/objects/5e/d6b40973a5f1b3b59759619a5ec452379beb09 new file mode 100644 index 0000000..ba43a4c Binary files /dev/null and b/kernel/git folder/objects/5e/d6b40973a5f1b3b59759619a5ec452379beb09 differ diff --git a/kernel/git folder/objects/5f/a3756bb01bea97f70d7467208bdfd0fabb04da b/kernel/git folder/objects/5f/a3756bb01bea97f70d7467208bdfd0fabb04da new file mode 100644 index 0000000..50c4d17 Binary files /dev/null and b/kernel/git folder/objects/5f/a3756bb01bea97f70d7467208bdfd0fabb04da differ diff --git a/kernel/git folder/objects/62/dec2ea1de4bab03c91839ce915353d125315f3 b/kernel/git folder/objects/62/dec2ea1de4bab03c91839ce915353d125315f3 new file mode 100644 index 0000000..99a82b6 Binary files /dev/null and b/kernel/git folder/objects/62/dec2ea1de4bab03c91839ce915353d125315f3 differ diff --git a/kernel/git folder/objects/63/d989358c9a1732cc911cd246acfc0aa87ed7b8 b/kernel/git folder/objects/63/d989358c9a1732cc911cd246acfc0aa87ed7b8 new file mode 100644 index 0000000..5a67d7c Binary files /dev/null and b/kernel/git folder/objects/63/d989358c9a1732cc911cd246acfc0aa87ed7b8 differ diff --git a/kernel/git folder/objects/65/830db9ef02e106033f59627a724ee2baee8675 b/kernel/git folder/objects/65/830db9ef02e106033f59627a724ee2baee8675 new file mode 100644 index 0000000..1e90d30 Binary files /dev/null and b/kernel/git folder/objects/65/830db9ef02e106033f59627a724ee2baee8675 differ diff --git a/kernel/git folder/objects/6c/0352b6c42687e6aae527a8c8d46c8181a6091d b/kernel/git folder/objects/6c/0352b6c42687e6aae527a8c8d46c8181a6091d new file mode 100644 index 0000000..c0a8ae3 Binary files /dev/null and b/kernel/git folder/objects/6c/0352b6c42687e6aae527a8c8d46c8181a6091d differ diff --git a/kernel/git folder/objects/6c/da090e0a9a2f7516e79bd6b620602401b80dac b/kernel/git folder/objects/6c/da090e0a9a2f7516e79bd6b620602401b80dac new file mode 100644 index 0000000..0d2ce54 Binary files /dev/null and b/kernel/git folder/objects/6c/da090e0a9a2f7516e79bd6b620602401b80dac differ diff --git a/kernel/git folder/objects/6e/f7ef8aea2e41da5400af8d6287a95f9fa60975 b/kernel/git folder/objects/6e/f7ef8aea2e41da5400af8d6287a95f9fa60975 new file mode 100644 index 0000000..38283cf Binary files /dev/null and b/kernel/git folder/objects/6e/f7ef8aea2e41da5400af8d6287a95f9fa60975 differ diff --git a/kernel/git folder/objects/76/1cc707a175daab8564f4471bf9d0f93f3afab3 b/kernel/git folder/objects/76/1cc707a175daab8564f4471bf9d0f93f3afab3 new file mode 100644 index 0000000..6d3966d Binary files /dev/null and b/kernel/git folder/objects/76/1cc707a175daab8564f4471bf9d0f93f3afab3 differ diff --git a/kernel/git folder/objects/7d/3d5c7ecc8fa44dd8c92662331be6070ded20ed b/kernel/git folder/objects/7d/3d5c7ecc8fa44dd8c92662331be6070ded20ed new file mode 100644 index 0000000..bf703e8 Binary files /dev/null and b/kernel/git folder/objects/7d/3d5c7ecc8fa44dd8c92662331be6070ded20ed differ diff --git a/kernel/git folder/objects/7d/930abd7d8d1d1d42cdedaa5c90f8f837130a8e b/kernel/git folder/objects/7d/930abd7d8d1d1d42cdedaa5c90f8f837130a8e new file mode 100644 index 0000000..2f5db83 Binary files /dev/null and b/kernel/git folder/objects/7d/930abd7d8d1d1d42cdedaa5c90f8f837130a8e differ diff --git a/kernel/git folder/objects/80/474235e801f2e85cae0f34b8e80e6763fb76b9 b/kernel/git folder/objects/80/474235e801f2e85cae0f34b8e80e6763fb76b9 new file mode 100644 index 0000000..695f977 Binary files /dev/null and b/kernel/git folder/objects/80/474235e801f2e85cae0f34b8e80e6763fb76b9 differ diff --git a/kernel/git folder/objects/82/2955fb23c1764acba23486209aa9e924a0e9e8 b/kernel/git folder/objects/82/2955fb23c1764acba23486209aa9e924a0e9e8 new file mode 100644 index 0000000..a606bcf Binary files /dev/null and b/kernel/git folder/objects/82/2955fb23c1764acba23486209aa9e924a0e9e8 differ diff --git a/kernel/git folder/objects/82/fc48263ebe6ff566feca44eff714db65e88628 b/kernel/git folder/objects/82/fc48263ebe6ff566feca44eff714db65e88628 new file mode 100644 index 0000000..9413ae5 Binary files /dev/null and b/kernel/git folder/objects/82/fc48263ebe6ff566feca44eff714db65e88628 differ diff --git a/kernel/git folder/objects/83/187e61981fadf0b92af09de9203cffa71917f0 b/kernel/git folder/objects/83/187e61981fadf0b92af09de9203cffa71917f0 new file mode 100644 index 0000000..4c2a45d Binary files /dev/null and b/kernel/git folder/objects/83/187e61981fadf0b92af09de9203cffa71917f0 differ diff --git a/kernel/git folder/objects/85/46a3baa41cace749fb3f089de5f901aed8d294 b/kernel/git folder/objects/85/46a3baa41cace749fb3f089de5f901aed8d294 new file mode 100644 index 0000000..c9316f6 Binary files /dev/null and b/kernel/git folder/objects/85/46a3baa41cace749fb3f089de5f901aed8d294 differ diff --git a/kernel/git folder/objects/8d/361f3027ed65b6701d75fea64a7f903f57f41f b/kernel/git folder/objects/8d/361f3027ed65b6701d75fea64a7f903f57f41f new file mode 100644 index 0000000..09d1148 Binary files /dev/null and b/kernel/git folder/objects/8d/361f3027ed65b6701d75fea64a7f903f57f41f differ diff --git a/kernel/git folder/objects/8e/52b17a806cb11ea19389e644b1fe5c493cb462 b/kernel/git folder/objects/8e/52b17a806cb11ea19389e644b1fe5c493cb462 new file mode 100644 index 0000000..0b3b462 Binary files /dev/null and b/kernel/git folder/objects/8e/52b17a806cb11ea19389e644b1fe5c493cb462 differ diff --git a/kernel/git folder/objects/92/e9f029f62bd5ee14fab34c6485e839df5d2021 b/kernel/git folder/objects/92/e9f029f62bd5ee14fab34c6485e839df5d2021 new file mode 100644 index 0000000..99e197c Binary files /dev/null and b/kernel/git folder/objects/92/e9f029f62bd5ee14fab34c6485e839df5d2021 differ diff --git a/kernel/git folder/objects/95/debf8491c17eb14e8093e103900020d9db0281 b/kernel/git folder/objects/95/debf8491c17eb14e8093e103900020d9db0281 new file mode 100644 index 0000000..2196482 Binary files /dev/null and b/kernel/git folder/objects/95/debf8491c17eb14e8093e103900020d9db0281 differ diff --git a/kernel/git folder/objects/98/e2ab940bc5077d9be593e734ce708d00f53b25 b/kernel/git folder/objects/98/e2ab940bc5077d9be593e734ce708d00f53b25 new file mode 100644 index 0000000..9201d1d Binary files /dev/null and b/kernel/git folder/objects/98/e2ab940bc5077d9be593e734ce708d00f53b25 differ diff --git a/kernel/git folder/objects/9b/5879ea7ec7b69eab184dd020f5d58e4be98aa1 b/kernel/git folder/objects/9b/5879ea7ec7b69eab184dd020f5d58e4be98aa1 new file mode 100644 index 0000000..ba9cd94 Binary files /dev/null and b/kernel/git folder/objects/9b/5879ea7ec7b69eab184dd020f5d58e4be98aa1 differ diff --git a/kernel/git folder/objects/a1/4daa5afe8cab2309891ed708854b54024b9337 b/kernel/git folder/objects/a1/4daa5afe8cab2309891ed708854b54024b9337 new file mode 100644 index 0000000..34af860 Binary files /dev/null and b/kernel/git folder/objects/a1/4daa5afe8cab2309891ed708854b54024b9337 differ diff --git a/kernel/git folder/objects/af/950244bda933b297b9537fe85bbcb1f51be641 b/kernel/git folder/objects/af/950244bda933b297b9537fe85bbcb1f51be641 new file mode 100644 index 0000000..d032f0f Binary files /dev/null and b/kernel/git folder/objects/af/950244bda933b297b9537fe85bbcb1f51be641 differ diff --git a/kernel/git folder/objects/af/bfce306060b1b96a96f5a57695ed0347c40b34 b/kernel/git folder/objects/af/bfce306060b1b96a96f5a57695ed0347c40b34 new file mode 100644 index 0000000..2ad3057 Binary files /dev/null and b/kernel/git folder/objects/af/bfce306060b1b96a96f5a57695ed0347c40b34 differ diff --git a/kernel/git folder/objects/c5/9b3a657ac7708a52f97269d323944f4b1a4cf3 b/kernel/git folder/objects/c5/9b3a657ac7708a52f97269d323944f4b1a4cf3 new file mode 100644 index 0000000..6b947f6 Binary files /dev/null and b/kernel/git folder/objects/c5/9b3a657ac7708a52f97269d323944f4b1a4cf3 differ diff --git a/kernel/git folder/objects/d2/a9c820ebd7dd73c699c4b83793ce43fd2ea9b1 b/kernel/git folder/objects/d2/a9c820ebd7dd73c699c4b83793ce43fd2ea9b1 new file mode 100644 index 0000000..0733171 Binary files /dev/null and b/kernel/git folder/objects/d2/a9c820ebd7dd73c699c4b83793ce43fd2ea9b1 differ diff --git a/kernel/git folder/objects/d5/e90eb6b4264f81aba09d1725f4e65bd253447c b/kernel/git folder/objects/d5/e90eb6b4264f81aba09d1725f4e65bd253447c new file mode 100644 index 0000000..3de6b0c Binary files /dev/null and b/kernel/git folder/objects/d5/e90eb6b4264f81aba09d1725f4e65bd253447c differ diff --git a/kernel/git folder/objects/d6/9a4945965daab95a9dc447f407cc905c854469 b/kernel/git folder/objects/d6/9a4945965daab95a9dc447f407cc905c854469 new file mode 100644 index 0000000..19e2877 Binary files /dev/null and b/kernel/git folder/objects/d6/9a4945965daab95a9dc447f407cc905c854469 differ diff --git a/kernel/git folder/objects/db/564cb381fc75e904278162037a4b68c58b5030 b/kernel/git folder/objects/db/564cb381fc75e904278162037a4b68c58b5030 new file mode 100644 index 0000000..6ef3e4d Binary files /dev/null and b/kernel/git folder/objects/db/564cb381fc75e904278162037a4b68c58b5030 differ diff --git a/kernel/git folder/objects/db/575d0d97b5731bf1194be5d5b9fde02105dba6 b/kernel/git folder/objects/db/575d0d97b5731bf1194be5d5b9fde02105dba6 new file mode 100644 index 0000000..75f392d Binary files /dev/null and b/kernel/git folder/objects/db/575d0d97b5731bf1194be5d5b9fde02105dba6 differ diff --git a/kernel/git folder/objects/de/4b45f94a1caf74227de6a5526d495ac6699c19 b/kernel/git folder/objects/de/4b45f94a1caf74227de6a5526d495ac6699c19 new file mode 100644 index 0000000..cc80e36 Binary files /dev/null and b/kernel/git folder/objects/de/4b45f94a1caf74227de6a5526d495ac6699c19 differ diff --git a/kernel/git folder/objects/e0/86b7ec68921b49d556a02aab834517d060624c b/kernel/git folder/objects/e0/86b7ec68921b49d556a02aab834517d060624c new file mode 100644 index 0000000..1d1568f Binary files /dev/null and b/kernel/git folder/objects/e0/86b7ec68921b49d556a02aab834517d060624c differ diff --git a/kernel/git folder/objects/e1/892cd1850bf56a978e827364c62063853085b2 b/kernel/git folder/objects/e1/892cd1850bf56a978e827364c62063853085b2 new file mode 100644 index 0000000..7e1e389 Binary files /dev/null and b/kernel/git folder/objects/e1/892cd1850bf56a978e827364c62063853085b2 differ diff --git a/kernel/git folder/objects/e2/0f35c2db40af80dcbfba67baa639811e14fd3f b/kernel/git folder/objects/e2/0f35c2db40af80dcbfba67baa639811e14fd3f new file mode 100644 index 0000000..c493db7 Binary files /dev/null and b/kernel/git folder/objects/e2/0f35c2db40af80dcbfba67baa639811e14fd3f differ diff --git a/kernel/git folder/objects/e9/4355d449d236de792dbcec34f872b917dabb3e b/kernel/git folder/objects/e9/4355d449d236de792dbcec34f872b917dabb3e new file mode 100644 index 0000000..1b70409 Binary files /dev/null and b/kernel/git folder/objects/e9/4355d449d236de792dbcec34f872b917dabb3e differ diff --git a/kernel/git folder/objects/f5/bd50dce081e1b31d98a5366d95dfae95010293 b/kernel/git folder/objects/f5/bd50dce081e1b31d98a5366d95dfae95010293 new file mode 100644 index 0000000..ce941d5 Binary files /dev/null and b/kernel/git folder/objects/f5/bd50dce081e1b31d98a5366d95dfae95010293 differ diff --git a/kernel/git folder/objects/pack/pack-3cfdf801d51f259f5767bda7d5b22bcd16fcdee7.idx b/kernel/git folder/objects/pack/pack-3cfdf801d51f259f5767bda7d5b22bcd16fcdee7.idx new file mode 100644 index 0000000..5124b48 Binary files /dev/null and b/kernel/git folder/objects/pack/pack-3cfdf801d51f259f5767bda7d5b22bcd16fcdee7.idx differ diff --git a/kernel/git folder/objects/pack/pack-3cfdf801d51f259f5767bda7d5b22bcd16fcdee7.pack b/kernel/git folder/objects/pack/pack-3cfdf801d51f259f5767bda7d5b22bcd16fcdee7.pack new file mode 100644 index 0000000..0d8081a Binary files /dev/null and b/kernel/git folder/objects/pack/pack-3cfdf801d51f259f5767bda7d5b22bcd16fcdee7.pack differ diff --git a/kernel/git folder/objects/pack/pack-3cfdf801d51f259f5767bda7d5b22bcd16fcdee7.rev b/kernel/git folder/objects/pack/pack-3cfdf801d51f259f5767bda7d5b22bcd16fcdee7.rev new file mode 100644 index 0000000..1829ef1 Binary files /dev/null and b/kernel/git folder/objects/pack/pack-3cfdf801d51f259f5767bda7d5b22bcd16fcdee7.rev differ diff --git a/kernel/git folder/packed-refs b/kernel/git folder/packed-refs new file mode 100644 index 0000000..250f187 --- /dev/null +++ b/kernel/git folder/packed-refs @@ -0,0 +1 @@ +# pack-refs with: peeled fully-peeled sorted diff --git a/kernel/git folder/refs/heads/main b/kernel/git folder/refs/heads/main new file mode 100644 index 0000000..2070c02 --- /dev/null +++ b/kernel/git folder/refs/heads/main @@ -0,0 +1 @@ +42e87e1d3dbc0a7e79b354179d301887d9cba722 diff --git a/kernel/git folder/refs/remotes/origin/HEAD b/kernel/git folder/refs/remotes/origin/HEAD new file mode 100644 index 0000000..4b0a875 --- /dev/null +++ b/kernel/git folder/refs/remotes/origin/HEAD @@ -0,0 +1 @@ +ref: refs/remotes/origin/main diff --git a/kernel/git folder/refs/remotes/origin/main b/kernel/git folder/refs/remotes/origin/main new file mode 100644 index 0000000..2070c02 --- /dev/null +++ b/kernel/git folder/refs/remotes/origin/main @@ -0,0 +1 @@ +42e87e1d3dbc0a7e79b354179d301887d9cba722 diff --git a/kernel/git folder/refs/remotes/upstream/HEAD b/kernel/git folder/refs/remotes/upstream/HEAD new file mode 100644 index 0000000..abc5c6f --- /dev/null +++ b/kernel/git folder/refs/remotes/upstream/HEAD @@ -0,0 +1 @@ +ref: refs/remotes/upstream/main diff --git a/kernel/git folder/refs/remotes/upstream/main b/kernel/git folder/refs/remotes/upstream/main new file mode 100644 index 0000000..2ae026b --- /dev/null +++ b/kernel/git folder/refs/remotes/upstream/main @@ -0,0 +1 @@ +24761e3a8c04bdd94bf75277ea352e7ffaac417e diff --git a/kernel/kernel.ld b/kernel/kernel.ld new file mode 100644 index 0000000..3b95efa --- /dev/null +++ b/kernel/kernel.ld @@ -0,0 +1,23 @@ +OUTPUT_FORMAT(elf64-x86-64) +ENTRY(_start) + +SECTIONS +{ + .text : ALIGN(0x1000) + { + *(.text) + } + .data : ALIGN(0x1000) + { + *(.data) + } + .rodata : ALIGN(0x1000) + { + *(.rodata) + } + .bss : ALIGN(0x1000) + { + *(COMMON) + *(.bss) + } +} \ No newline at end of file diff --git a/kernel/lib/BasicRenderer.o b/kernel/lib/BasicRenderer.o new file mode 100644 index 0000000..9b5879e Binary files /dev/null and b/kernel/lib/BasicRenderer.o differ diff --git a/kernel/lib/kernel.o b/kernel/lib/kernel.o new file mode 100644 index 0000000..8546a3b Binary files /dev/null and b/kernel/lib/kernel.o differ diff --git a/kernel/run.bat b/kernel/run.bat new file mode 100644 index 0000000..2482315 --- /dev/null +++ b/kernel/run.bat @@ -0,0 +1,6 @@ +set OSNAME=CustomOS +set BUILDDIR=%0/../bin +set OVMFDIR=%0/../../OVMFbin + +qemu-system-x86_64 -drive file=%BUILDDIR%/%OSNAME%.img -m 256M -cpu qemu64 -drive if=pflash,format=raw,unit=0,file="%OVMFDIR%/OVMF_CODE-pure-efi.fd",readonly=on -drive if=pflash,format=raw,unit=1,file="%OVMFDIR%/OVMF_VARS-pure-efi.fd" -net none +pause diff --git a/kernel/run2.bat b/kernel/run2.bat new file mode 100644 index 0000000..bf8c7d8 --- /dev/null +++ b/kernel/run2.bat @@ -0,0 +1,8 @@ +set OSNAME=CustomOS +set BUILDDIR=%0/../bin +set OVMFDIR=%0/../../OVMFbin + +set BUILDDIR=%BUILDDIR:"=% +set OVMFDIR=%OVMFDIR:"=% +qemu-system-x86_64 -drive file=%BUILDDIR%/%OSNAME%.img -m 256M -cpu qemu64 -drive if=pflash,format=raw,unit=0,file=%OVMFDIR%/OVMF_CODE-pure-efi.fd,readonly=on -drive if=pflash,format=raw,unit=1,file=%OVMFDIR%/OVMF_VARS-pure-efi.fd -net none +pause diff --git a/kernel/src/BasicRenderer.cpp b/kernel/src/BasicRenderer.cpp new file mode 100644 index 0000000..62dec2e --- /dev/null +++ b/kernel/src/BasicRenderer.cpp @@ -0,0 +1,40 @@ +#include "BasicRenderer.h" + +BasicRenderer::BasicRenderer(Framebuffer* framebuffer, PSF1_FONT* psf1_Font) { + targetFramebuffer = framebuffer; + PSF1_Font = psf1_Font; + cursorPosition = {0,0}; +} + +void BasicRenderer::PutChar(unsigned int colour, char chr, unsigned int xOff, unsigned int yOff) { + unsigned int* pixPtr = (unsigned int*)targetFramebuffer->BaseAddress; + char* fontPtr = (char*)PSF1_Font->glyphBuffer + (chr * PSF1_Font->psf1_Header->charsize); + for (unsigned long y = yOff; y < yOff + 18; y++) { + for (unsigned long x = xOff; x < xOff+8; x++) { + + if ((*fontPtr & (0b10000000 >> (x - xOff))) > 0) { + *(unsigned int*)(pixPtr + x + (y * targetFramebuffer->PixelsPerScanline)) = colour; + } + + } + + fontPtr++; + } +} + +void BasicRenderer::Print(unsigned int colour, const char* str) { + unsigned int x = 0; + char* chr = (char*)str; + + while (*chr != 0) { + PutChar(colour, *chr, cursorPosition.x, cursorPosition.y); + cursorPosition.x+=8; + + if (cursorPosition.x + 8 > targetFramebuffer->Width) { + cursorPosition.x = 0; + cursorPosition.y += 18; + } + + chr++; + } +} \ No newline at end of file diff --git a/kernel/src/BasicRenderer.h b/kernel/src/BasicRenderer.h new file mode 100644 index 0000000..d5e90eb --- /dev/null +++ b/kernel/src/BasicRenderer.h @@ -0,0 +1,14 @@ +#pragma once +#include "math.h" +#include "Framebuffer.h" +#include "PSF1Font.h" + +class BasicRenderer { + public: + BasicRenderer(Framebuffer* framebuffer, PSF1_FONT* psf1_Font); + Point cursorPosition; + Framebuffer* targetFramebuffer; + PSF1_FONT* PSF1_Font; + void Print(unsigned int colour, const char* str); + void PutChar(unsigned int colour, char chr, unsigned int xOff, unsigned int yOff); +}; \ No newline at end of file diff --git a/kernel/src/Framebuffer.h b/kernel/src/Framebuffer.h new file mode 100644 index 0000000..6cda090 --- /dev/null +++ b/kernel/src/Framebuffer.h @@ -0,0 +1,10 @@ +#pragma once +#include + +struct Framebuffer { + void* BaseAddress; + size_t BufferSize; + unsigned int Width; + unsigned int Height; + unsigned int PixelsPerScanline; +}; \ No newline at end of file diff --git a/kernel/src/PSF1Font.h b/kernel/src/PSF1Font.h new file mode 100644 index 0000000..c59b3a6 --- /dev/null +++ b/kernel/src/PSF1Font.h @@ -0,0 +1,12 @@ +#pragma once + +struct PSF1_HEADER { + unsigned char magic[2]; + unsigned char mode; + unsigned char charsize; +}; + +struct PSF1_FONT { + PSF1_HEADER* psf1_Header; + void* glyphBuffer; +}; \ No newline at end of file diff --git a/kernel/src/kernel.cpp b/kernel/src/kernel.cpp new file mode 100644 index 0000000..06b55af --- /dev/null +++ b/kernel/src/kernel.cpp @@ -0,0 +1,17 @@ +#include +#include +#include "BasicRenderer.h" + + +// supposed to protect against stack smashing but we have no way to actually like +// do anything when we detect it soooo... +extern "C" void __stack_chk_fail(void) { + return; +} + +extern "C" void _start(Framebuffer* framebuffer, PSF1_FONT* psf1_Font) { + BasicRenderer newRenderer = BasicRenderer(framebuffer, psf1_Font); + newRenderer.Print(0xFFFFFF, "Hello, World!"); + + return; +} \ No newline at end of file diff --git a/kernel/src/math.h b/kernel/src/math.h new file mode 100644 index 0000000..a14daa5 --- /dev/null +++ b/kernel/src/math.h @@ -0,0 +1,6 @@ +#pragma once + +struct Point { + unsigned int x; + unsigned int y; +}; \ No newline at end of file diff --git a/kernel/startup.nsh b/kernel/startup.nsh new file mode 100644 index 0000000..228930a --- /dev/null +++ b/kernel/startup.nsh @@ -0,0 +1,68 @@ +@echo -off +mode 80 25 + +cls +if exist .\efi\boot\main.efi then + .\efi\boot\main.efi + goto END +endif + +if exist fs0:\efi\boot\main.efi then + fs0: + echo Found bootloader on fs0: + efi\boot\main.efi + goto END +endif + +if exist fs1:\efi\boot\main.efi then + fs1: + echo Found bootloader on fs1: + efi\boot\main.efi + goto END +endif + +if exist fs2:\efi\boot\main.efi then + fs2: + echo Found bootloader on fs2: + efi\boot\main.efi + goto END +endif + +if exist fs3:\efi\boot\main.efi then + fs3: + echo Found bootloader on fs3: + efi\boot\main.efi + goto END +endif + +if exist fs4:\efi\boot\main.efi then + fs4: + echo Found bootloader on fs4: + efi\boot\main.efi + goto END +endif + +if exist fs5:\efi\boot\main.efi then + fs5: + echo Found bootloader on fs5: + efi\boot\main.efi + goto END +endif + +if exist fs6:\efi\boot\main.efi then + fs6: + echo Found bootloader on fs6: + efi\boot\main.efi + goto END +endif + +if exist fs7:\efi\boot\main.efi then + fs7: + echo Found bootloader on fs7: + efi\boot\main.efi + goto END +endif + + echo "Unable to find bootloader". + +:END