Age | Commit message (Collapse) | Author |
|
Provide access to the MIDR_EL1 register to obtain the
main id for determining CPU implementer and part/revision
information.
BUG=chrome-os-partner:31761
BRANCH=None
TEST=Built and printed the output of this function on ryu.
Change-Id: I42cec75072fc5e8b48f63c1971840fdc415e4326
Signed-off-by: Patrick Georgi <pgeorgi@chromium.org>
Original-Commit-Id: ad19ffe629d9f16b8fd07051ce73533e97fb3f5c
Original-Change-Id: I8b8506ebff8e6f9d7c4f96d7ff7e21803972961e
Original-Signed-off-by: Aaron Durbin <adurbin@chromium.org>
Original-Reviewed-on: https://chromium-review.googlesource.com/216423
Original-Reviewed-by: Furquan Shaikh <furquan@chromium.org>
Reviewed-on: http://review.coreboot.org/9032
Tested-by: build bot (Jenkins)
Reviewed-by: Paul Menzel <paulepanter@users.sourceforge.net>
Reviewed-by: Stefan Reinauer <stefan.reinauer@coreboot.org>
|
|
Provides a minimal API for coordinating with the SoC for
bringing up the secondary CPUs. There's no eventloop or
dispatcher currently nor does it do anything proper when
one of the secondary CPUs are brought up. Those decisions
are deferred to the SoC.
BUG=chrome-os-partner:31545
BRANCH=None
TEST=Built and brought up 2nd cpu using this API.
Change-Id: I8ac0418282e2e5b4ab3abfd21c88f51d704e10f9
Signed-off-by: Patrick Georgi <pgeorgi@chromium.org>
Original-Commit-Id: 5303ae3d6bfc9f8f908fcb890e184eb9b57f1376
Original-Change-Id: I3b7334b7d2df2df093cdc0cbb997e8230d3b2685
Original-Signed-off-by: Aaron Durbin <adurbin@chromium.org>
Original-Reviewed-on: https://chromium-review.googlesource.com/214775
Original-Reviewed-by: Furquan Shaikh <furquan@chromium.org>
Reviewed-on: http://review.coreboot.org/9019
Tested-by: build bot (Jenkins)
Reviewed-by: Stefan Reinauer <stefan.reinauer@coreboot.org>
|
|
exception_hwinit() provides a path for just setting the hardware
state. This allows for other CPUs but the boot CPU for setting up
the appropriate vector table.
BUG=chrome-os-partner:31545
BRANCH=None
TEST=Built and booted to the kernel.
Change-Id: Ifd44ab697bce5cd351f05069519785dc80e2b866
Signed-off-by: Patrick Georgi <pgeorgi@chromium.org>
Original-Commit-Id: 76a1c9cb3df930b28469608ecb5c35be7ccdadd1
Original-Change-Id: Ib09c813b49a4f00daca0b53d9dca972251fcf476
Original-Signed-off-by: Aaron Durbin <adurbin@chromium.org>
Original-Reviewed-on: https://chromium-review.googlesource.com/214773
Original-Reviewed-by: Furquan Shaikh <furquan@chromium.org>
Reviewed-on: http://review.coreboot.org/9017
Tested-by: build bot (Jenkins)
Reviewed-by: Stefan Reinauer <stefan.reinauer@coreboot.org>
|
|
No need to pass in the same value for the ttb after just
calling mmu_init(). All current users are setting this once
and forgetting it.
BUG=chrome-os-partner:31545
BRANCH=None
TEST=Built and booted on ryu.
Change-Id: Ie446d16eaf4ea65a34a9c76dd7c6c2f9b19c5d57
Signed-off-by: Patrick Georgi <pgeorgi@chromium.org>
Original-Commit-Id: bd77461d483b513a569365673c83badc752f4aa8
Original-Change-Id: I54c7e4892d44ea6129429d8a46461d089dd8e2a9
Original-Signed-off-by: Aaron Durbin <adurbin@chromium.org>
Original-Reviewed-on: https://chromium-review.googlesource.com/214772
Original-Reviewed-by: Furquan Shaikh <furquan@chromium.org>
Reviewed-on: http://review.coreboot.org/9016
Tested-by: build bot (Jenkins)
Reviewed-by: Stefan Reinauer <stefan.reinauer@coreboot.org>
|
|
Instead of defining the stacks by Kconfig options include
the stack sizes for all the CPUs including each of their
exception stacks. This allows for providing each CPU
on startup a stack to work with.
Note: this currently inherits CONFIG_STACK_SIZE from x86 because
of the Kconfig mess of options not being guarded.
BUG=chrome-os-partner:31545
BRANCH=None
TEST=Built and booted into the kernel on ryu.
Change-Id: Ie5fa1a8b78ed808a14efeb1717b98d6b0dd85eef
Signed-off-by: Patrick Georgi <pgeorgi@chromium.org>
Original-Commit-Id: 6524993f016aac2ac8cd9dba9fbdd9a59260a2b6
Original-Change-Id: Ica09dc256e6ce1dd032433d071894af5f445acdb
Original-Signed-off-by: Aaron Durbin <adurbin@chromium.org>
Original-Reviewed-on: https://chromium-review.googlesource.com/214669
Original-Reviewed-by: Furquan Shaikh <furquan@chromium.org>
Reviewed-on: http://review.coreboot.org/9013
Tested-by: build bot (Jenkins)
Reviewed-by: Stefan Reinauer <stefan.reinauer@coreboot.org>
|
|
Provide a common entry point arm64 cores coming out of reset. Also,
take into account CONFIG_ARM64_CPUS_START_IN_ELx to set the
correct SCTLR_ELx register. The SCR_EL3 initialization was removed
as that can be done in policy code in C later. Part of this refactor
allows for greater code reuse for the secure monitor.
BUG=chrome-os-partner:31545
BRANCH=None
TEST=built and booted to linux on ryu
Change-Id: I429f8fd0cdae78318ac171722fa1377924665401
Signed-off-by: Patrick Georgi <pgeorgi@chromium.org>
Original-Commit-Id: f92a5a01f07bc370735d75d695aedd8e2ab25608
Original-Change-Id: If16b3f979923ec8add59854db6bad4aaed35e3aa
Original-Signed-off-by: Aaron Durbin <adurbin@chromium.org>
Original-Reviewed-on: https://chromium-review.googlesource.com/214668
Original-Reviewed-by: Furquan Shaikh <furquan@chromium.org>
Reviewed-on: http://review.coreboot.org/9012
Tested-by: build bot (Jenkins)
Reviewed-by: Stefan Reinauer <stefan.reinauer@coreboot.org>
|
|
In order to accomodate MP on arm64 one needs to be able to determine
the current logical processor id. Because it depends on the SoC
implementation the SoC needs to provide this implementation.
BUG=chrome-os-partner:31545
BRANCH=None
TEST=Built.
Change-Id: I2f09df9bf7d4f829d8f45471bf7281a4ddba2fc8
Signed-off-by: Patrick Georgi <pgeorgi@chromium.org>
Original-Commit-Id: 6033e73d70c3b8296b36ff36b4b848b176917e12
Original-Change-Id: I9511b54b5a1ab340b0f1309b0d9976be68b50903
Original-Signed-off-by: Aaron Durbin <adurbin@chromium.org>
Original-Reviewed-on: https://chromium-review.googlesource.com/214663
Original-Reviewed-by: Furquan Shaikh <furquan@chromium.org>
Reviewed-on: http://review.coreboot.org/9007
Tested-by: build bot (Jenkins)
Reviewed-by: Stefan Reinauer <stefan.reinauer@coreboot.org>
|
|
BUG=chrome-os-partner:31515
BRANCH=None
TEST=test_exception generates a page fault which is handled by the exception
handler and execution continues after eret from the exception
Change-Id: Ie550492d2ed21b2c3009b5627f1e1a37429e6af0
Signed-off-by: Patrick Georgi <pgeorgi@chromium.org>
Original-Commit-Id: e29fe77745d10e840c02498e54a0c53835530e5e
Original-Change-Id: I29b7dabaece9b11a04ee3628d83513d30eb07b1d
Original-Signed-off-by: Furquan Shaikh <furquan@google.com>
Original-Reviewed-on: https://chromium-review.googlesource.com/213661
Original-Tested-by: Furquan Shaikh <furquan@chromium.org>
Original-Reviewed-by: Aaron Durbin <adurbin@chromium.org>
Original-Commit-Queue: Furquan Shaikh <furquan@chromium.org>
Reviewed-on: http://review.coreboot.org/9000
Tested-by: build bot (Jenkins)
Reviewed-by: Stefan Reinauer <stefan.reinauer@coreboot.org>
|
|
Non-cacheable normal memory is needed when one wants an easy way
to have a DMA region. That way all the reads and writes will be
picked up by the CPU and the device without any cache management
operations.
BUG=chrome-os-partner:31293
BRANCH=None
TEST=With a bevy of other patches can use a carved out DMA region
for talking to USB.
Change-Id: I8172f4b7510dee250aa561d040b27af3080764d7
Signed-off-by: Patrick Georgi <pgeorgi@chromium.org>
Original-Commit-Id: a5bc7ab1709edd97d8795aa9687e6a0edf26ffc6
Original-Change-Id: I36b7fc276467fe3e9cec4d602652d6fa8098c133
Original-Signed-off-by: Aaron Durbin <adurbin@chromium.org>
Original-Reviewed-on: https://chromium-review.googlesource.com/212160
Original-Reviewed-by: Furquan Shaikh <furquan@chromium.org>
Original-Commit-Queue: Furquan Shaikh <furquan@chromium.org>
Reviewed-on: http://review.coreboot.org/8924
Tested-by: build bot (Jenkins)
Reviewed-by: Stefan Reinauer <stefan.reinauer@coreboot.org>
|
|
BUG=None
BRANCH=None
TEST=Compiles successfully
Original-Change-Id: I395c9b7bbe34c6834abc1a169779639f940121bd
Original-Signed-off-by: Furquan Shaikh <furquan@google.com>
Original-Reviewed-on: https://chromium-review.googlesource.com/209334
Original-Tested-by: Furquan Shaikh <furquan@chromium.org>
Original-Reviewed-by: Aaron Durbin <adurbin@chromium.org>
Original-Commit-Queue: Furquan Shaikh <furquan@chromium.org>
(cherry picked from commit da15df16464f4203db08fb02ad4c0a0f94d16724)
Signed-off-by: Marc Jones <marc.jones@se-eng.com>
Change-Id: I818de7cb0d8a44fb20c2bbea108c15ecc2b724ae
Reviewed-on: http://review.coreboot.org/8650
Tested-by: build bot (Jenkins)
Reviewed-by: Paul Menzel <paulepanter@users.sourceforge.net>
Reviewed-by: Patrick Georgi <pgeorgi@google.com>
|
|
Add support for initializing and enabling mmu for armv8. Using 64KiB granule and
33 bits per VA, thus total VA address space is 6GiB. PA Range is 64GiB. Makes
use of memrange library to get a list of all the mmap regions from the SoC to
initialize XLAT table.
Currently, all calculations in mmu.h are based on the assumptions that max 33
bits are used in VA and granule size is 64KiB. Changes in these assumptions will
have to reflect in the dependent calculations as well.
BUG=chrome-os-partner:30688
BRANCH=None
TEST=Compiles rush successfully and boots until "payload not found". Goes past
all the earlier alignment errors.
Original-Change-Id: Iac1df15f0b81dcf64484a56b94f51357bcd67cc2
Original-Signed-off-by: Furquan Shaikh <furquan@google.com>
Original-Reviewed-on: https://chromium-review.googlesource.com/208761
Original-Tested-by: Furquan Shaikh <furquan@chromium.org>
Original-Reviewed-by: Aaron Durbin <adurbin@chromium.org>
Original-Commit-Queue: Furquan Shaikh <furquan@chromium.org>
(cherry picked from commit 6fe96360c03342115f849074f9e45a2c4e210705)
Signed-off-by: Marc Jones <marc.jones@se-eng.com>
Change-Id: I5360a3be95f198bd0b4f79b62f31228cc7a9c285
Reviewed-on: http://review.coreboot.org/8646
Reviewed-by: Furquan Shaikh <furquan@google.com>
Tested-by: build bot (Jenkins)
|
|
Some of the SoC's need an early hook to configure
certain registers. One example of this is on t132
where ramstage is the first thing being ran on the
arm64 core and it is the only entity that can configure
certain registers required for the rest of ramstage.
Therefore, provide the opportunity for the SoC to
implement such requirements.
BUG=chrome-os-partner:30572
BRANCH=None
TEST=Built and ran through coreboot.
Original-Change-Id: Ib352f3788872f888581b398c9b394b7c4e54b02a
Original-Signed-off-by: Aaron Durbin <adurbin@chromium.org>
Original-Reviewed-on: https://chromium-review.googlesource.com/208061
Original-Reviewed-by: Tom Warren <twarren@nvidia.com>
Original-Reviewed-by: Furquan Shaikh <furquan@chromium.org>
Original-Commit-Queue: Furquan Shaikh <furquan@chromium.org>
(cherry picked from commit 2c50e2b39e75d1383e8e573c576630a5b7313349)
Signed-off-by: Marc Jones <marc.jones@se-eng.com>
Change-Id: I38df63e46c5c21b2d319fc9eb42053c3a0d61bc8
Reviewed-on: http://review.coreboot.org/8595
Tested-by: build bot (Jenkins)
Reviewed-by: Aaron Durbin <adurbin@google.com>
Reviewed-by: Paul Menzel <paulepanter@users.sourceforge.net>
|
|
Ramstage needs an assembly entry point for setting up
the initial state of the CPU. Therefore, a function is
provided, arm64_el3_startup(), that bootstraps the state
of the processor, initializes the stack pointer, and
branches to a defined entry symbol. To make this work
without adding too much preprocessor macro conditions
provide _stack and _estack for all the stages.
Currently the entry point after initialization is 'main',
however it can be changed/extended to do more work such
as seeding the stack contents with tombstones, etc.
It should be noted that romstage and bootblock weren't
tested. Only ramstage is known to work.
BUG=chrome-os-partner:29923
BRANCH=None
TEST=Brought up 64-bit ramstage on rush.
Original-Change-Id: I1f07d5b6656e13e6667b038cdc1f4be8843d1960
Original-Signed-off-by: Aaron Durbin <adurbin@chromium.org>
Original-Reviewed-on: https://chromium-review.googlesource.com/207262
Original-Reviewed-by: Furquan Shaikh <furquan@chromium.org>
(cherry picked from commit 7850ee3a7bf48c05f2e64147edb92161f8308f19)
Signed-off-by: Marc Jones <marc.jones@se-eng.com>
Change-Id: Ia87697f49638c8c249215d441d95f1ec621e0949
Reviewed-on: http://review.coreboot.org/8585
Tested-by: build bot (Jenkins)
Reviewed-by: Aaron Durbin <adurbin@google.com>
|
|
Correct function names to make them consistent with generic calling name
BUG=None
BRANCH=None
TEST=Compiles successfully for rush
Original-Change-Id: I50499936e1c8da0aafd7e36a22c2c6ab373230f6
Original-Signed-off-by: Furquan Shaikh <furquan@google.com>
Original-Reviewed-on: https://chromium-review.googlesource.com/205582
Original-Tested-by: Furquan Shaikh <furquan@chromium.org>
Original-Reviewed-by: Aaron Durbin <adurbin@chromium.org>
Original-Commit-Queue: Aaron Durbin <adurbin@chromium.org>
(cherry picked from commit 16668529527224fca3086ee88955d29e3a268516)
Signed-off-by: Marc Jones <marc.jones@se-eng.com>
Change-Id: I449e63b05680ca12ae81a3260fc03836686d7317
Reviewed-on: http://review.coreboot.org/8469
Tested-by: build bot (Jenkins)
Reviewed-by: Paul Menzel <paulepanter@users.sourceforge.net>
Reviewed-by: Aaron Durbin <adurbin@google.com>
|
|
Define functions for setting cntfrq register in arm and arm64 arch. This allows
SoCs to set this register independently of the architecture being used.
BUG=None
BRANCH=None
TEST=Compiles successfully for nyan and rush
Original-Change-Id: I93240419b2c012eee29a408deff34a42af943a63
Original-Signed-off-by: Furquan Shaikh <furquan@google.com>
Original-Reviewed-on: https://chromium-review.googlesource.com/205580
Original-Tested-by: Furquan Shaikh <furquan@chromium.org>
Original-Reviewed-by: Aaron Durbin <adurbin@chromium.org>
Original-Commit-Queue: Aaron Durbin <adurbin@chromium.org>
(cherry picked from commit 768463fef5d630dec915aa0b95e7724d4a6f74b6)
armv8: GPL license armv8 lib
BUG=None
BRANCH=None
TEST=Compiles successfully.
Original-Change-Id: Ibe0f09ef6704ad808cc482ffec27a4db32d7f6fd
Original-Signed-off-by: Furquan Shaikh <furquan@google.com>
Original-Reviewed-on: https://chromium-review.googlesource.com/250950
Original-Trybot-Ready: Furquan Shaikh <furquan@chromium.org>
Original-Tested-by: Furquan Shaikh <furquan@chromium.org>
Original-Reviewed-by: Aaron Durbin <adurbin@chromium.org>
Original-Commit-Queue: Furquan Shaikh <furquan@chromium.org>
(cherry picked from commit bc115869bb0bcedbc284677ca5743b9ab40bfc7e)
Signed-off-by: Marc Jones <marc.jones@se-eng.com>
Change-Id: I298c3e76cb52f0876bce3dd4f54d875f62e9310a
Reviewed-on: http://review.coreboot.org/8468
Tested-by: build bot (Jenkins)
Reviewed-by: Paul Menzel <paulepanter@users.sourceforge.net>
Reviewed-by: Aaron Durbin <adurbin@google.com>
|
|
Add support for library functions required to access different system registers:
1) PSTATE and special purpose registers
2) System control registers
3) Cache-related registers
4) TLB maintenance registers
5) Misc barrier related functions
BUG=None
BRANCH=None
TEST=Compiles successfully
Original-Change-Id: I8809ca2b67b8e560b34577cda1483ee009a1d71a
Original-Signed-off-by: Furquan Shaikh <furquan@google.com>
Original-Reviewed-on: https://chromium-review.googlesource.com/203490
Original-Tested-by: Furquan Shaikh <furquan@chromium.org>
Original-Reviewed-by: Aaron Durbin <adurbin@chromium.org>
Original-Commit-Queue: Furquan Shaikh <furquan@chromium.org>
(cherry picked from commit 5da840c5d1f3d8fdf8cc0d7c44772bf0cef03fbb)
armv8: GPL license armv8 lib
BUG=None
BRANCH=None
TEST=Compiles successfully.
Original-Change-Id: Ibe0f09ef6704ad808cc482ffec27a4db32d7f6fd
Original-Signed-off-by: Furquan Shaikh <furquan@google.com>
Original-Reviewed-on: https://chromium-review.googlesource.com/250950
Original-Trybot-Ready: Furquan Shaikh <furquan@chromium.org>
Original-Tested-by: Furquan Shaikh <furquan@chromium.org>
Original-Reviewed-by: Aaron Durbin <adurbin@chromium.org>
Original-Commit-Queue: Furquan Shaikh <furquan@chromium.org>
(cherry picked from commit bc115869bb0bcedbc284677ca5743b9ab40bfc7e)
Get the library and the GPL license in a single commit.
Signed-off-by: Marc Jones <marc.jones@se-eng.com>
Change-Id: I4753a6b0d13a6f7515243bfa8e749e250fdd749d
Reviewed-on: http://review.coreboot.org/8465
Tested-by: build bot (Jenkins)
Reviewed-by: Aaron Durbin <adurbin@google.com>
Reviewed-by: Paul Menzel <paulepanter@users.sourceforge.net>
|
|
BUG=None
BRANCH=None
TEST=Compiles successfully for rush
Original-Change-Id: Ic8f5d91f6635ef12845ab049a20df5a6e33bbf55
Original-Signed-off-by: Furquan Shaikh <furquan@google.com>
Original-Reviewed-on: https://chromium-review.googlesource.com/203142
Original-Tested-by: Furquan Shaikh <furquan@chromium.org>
Original-Reviewed-by: Aaron Durbin <adurbin@chromium.org>
Original-Commit-Queue: Aaron Durbin <adurbin@chromium.org>
(cherry picked from commit ecf7822812d8745af74eaf135b7b806c23ef51a2)
Signed-off-by: Marc Jones <marc.jones@se-eng.com>
Change-Id: I79abbded94376ba90a8c729aaf856ce303509e48
Reviewed-on: http://review.coreboot.org/8410
Reviewed-by: Furquan Shaikh <furquan@google.com>
Reviewed-by: Aaron Durbin <adurbin@google.com>
Tested-by: Marc Jones <marc.jones@se-eng.com>
|
|
Although bool normally belongs in stdbool.h, for our use cases,
providing these definitions in stdint.h is acceptable.
Change-Id: I1d0ca1018efacc27d7a4a72aa452912e004401f9
Signed-off-by: Alexandru Gagniuc <mr.nuke.me@gmail.com>
Reviewed-on: http://review.coreboot.org/8279
Reviewed-by: Paul Menzel <paulepanter@users.sourceforge.net>
Tested-by: build bot (Jenkins)
Reviewed-by: Aaron Durbin <adurbin@gmail.com>
|
|
Move the CAR migration call to arch -specific part of CBMEM init,
it is truly a x86 specific thing.
Change-Id: I715417e54f197b8745e0670d6b900a5660178141
Signed-off-by: Kyösti Mälkki <kyosti.malkki@gmail.com>
Reviewed-on: http://review.coreboot.org/7860
Reviewed-by: Aaron Durbin <adurbin@google.com>
Tested-by: build bot (Jenkins)
|
|
With the change it becomes irrelevant if memcpy() car.global_data or
cbmemc_reinit() is done first.
Change-Id: Ie479eef346c959e97dcc55861ccb0db1321fb7b2
Signed-off-by: Kyösti Mälkki <kyosti.malkki@gmail.com>
Reviewed-on: http://review.coreboot.org/8032
Reviewed-by: Stefan Reinauer <stefan.reinauer@coreboot.org>
Reviewed-by: Aaron Durbin <adurbin@google.com>
Tested-by: build bot (Jenkins)
|
|
There were a number of issues with the ARM64 build files. This
patch ports the following changes from ARMV4/V7 to ARMV8:
- make armv8 Kconfig options consistent with armv4/v7
- fix build include issues in boot.c, tables.c,
and early_variables.h by matching armv4/v7.
Change-Id: I57359a96821d88c50f48dc0bb6ad226cacb0c2ec
Signed-off-by: Marc Jones <marc.jones@se-eng.com>
Change-Id: Iacd95d336559c45458784d1da67bde62a0956620
Reviewed-on: http://review.coreboot.org/8236
Tested-by: build bot (Jenkins)
Reviewed-by: Stefan Reinauer <stefan.reinauer@coreboot.org>
|
|
Add support for enabling different coreboot stages (bootblock, romstage and
ramstage) to have arm64 architecture. Most of the files have been copied over
from arm/ or arm64-generic work.
Signed-off-by: Furquan Shaikh <furquan@google.com>
Reviewed-on: https://chromium-review.googlesource.com/197397
Reviewed-by: Aaron Durbin <adurbin@chromium.org>
Commit-Queue: Furquan Shaikh <furquan@chromium.org>
Tested-by: Furquan Shaikh <furquan@chromium.org>
(cherry picked from commit 033ba96516805502673ac7404bc97e6ce4e2a934)
This patch is essentially a squash of aarch64 changes made by
these patches:
d955885 coreboot: Rename coreboot_ram stage to ramstage
a492761 cbmem console: Locate the preram console with a symbol instead of a sect
96e7f0e aarch64: Enable early icache and migrate SCTLR from EL3
3f854dc aarch64: Pass coreboot table in jmp_to_elf_entry
ab3ecaf aarch64/foundation-armv8: Set up RAM area and enter ramstage
25fd2e9 aarch64: Remove CAR definitions from early_variables.h
65bf77d aarch64/foundation-armv8: Enable DYNAMIC_CBMEM
9484873 aarch64: Change default exception level to EL2
7a152c3 aarch64: Fix formatting of exception registers dump
6946464 aarch64: Implement basic exception handling
c732a9d aarch64/foundation-armv8: Basic bootblock implementation
3bc412c aarch64: Comment out some parts of code to allow build
ab5be71 Add initial aarch64 support
The ramstage support is the only portion that has been tested
on actual hardware. Bootblock and romstage support may require
modifications to run on hardware.
Change-Id: Icd59bec55c963a471a50e30972a8092e4c9d2fb2
Signed-off-by: Isaac Christensen <isaac.christensen@se-eng.com>
Reviewed-on: http://review.coreboot.org/6915
Tested-by: build bot (Jenkins)
Reviewed-by: Edward O'Callaghan <eocallaghan@alterapraxis.com>
Reviewed-by: Furquan Shaikh <furquan@google.com>
|