#
f86bcc87
|
| 25-Aug-2023 |
Ed Tanous <edtanous@google.com> |
Clean up tftp update to use URL
Similar to transforms we've done elsewhere, we shouldn't be parsing urls using std::string::find, regex, or anything else, as they don't handle URL % encoding properl
Clean up tftp update to use URL
Similar to transforms we've done elsewhere, we shouldn't be parsing urls using std::string::find, regex, or anything else, as they don't handle URL % encoding properly.
Change-Id: I48bb30c0c737c4df2ae73f40fc49c63bac5b658f Signed-off-by: Ed Tanous <edtanous@google.com>
show more ...
|
#
8ece0e45
|
| 02-Jan-2024 |
Ed Tanous <ed@tanous.net> |
Fix spelling mistakes
These were found with: codespell -w $(git ls-files | grep "\.[hc]\(pp\)\?$")
At some point in the future, we might want to get this enabled in CI.
Change-Id: Iccb57b2adfd06a2
Fix spelling mistakes
These were found with: codespell -w $(git ls-files | grep "\.[hc]\(pp\)\?$")
At some point in the future, we might want to get this enabled in CI.
Change-Id: Iccb57b2adfd06a2e177e99db2923fe4e8e329118 Signed-off-by: Ed Tanous <ed@tanous.net>
show more ...
|
#
5a39f77a
|
| 20-Oct-2023 |
Patrick Williams <patrick@stwcx.xyz> |
clang-format: copy latest and re-format
clang-format-17 has some backwards incompatible changes that require additional settings for best compatibility and re-running the formatter. Copy the latest
clang-format: copy latest and re-format
clang-format-17 has some backwards incompatible changes that require additional settings for best compatibility and re-running the formatter. Copy the latest .clang-format from the docs repository and reformat the repository.
Change-Id: I2f9540cf0d545a2da4d6289fc87b754f684bc9a7 Signed-off-by: Patrick Williams <patrick@stwcx.xyz>
show more ...
|
#
4034a652
|
| 17-Aug-2023 |
Myung Bae <myungbae@us.ibm.com> |
Ignore Non-software-related events during Update
During code update, if another application (e.g. pldm[1]) logs an error unrelated to code update, this triggers an error event notification and cause
Ignore Non-software-related events during Update
During code update, if another application (e.g. pldm[1]) logs an error unrelated to code update, this triggers an error event notification and causes the code update failure.
``` $ uri=$(curl -k https://${bmc}/redfish/v1/UpdateService | jq -r ' .HttpPushUri'); echo $uri $ curl -k -H "Content-Type: application/octet-stream" -X POST -T ${image} https://${bmc}${uri} { "error": { ... "code": "Base.1.13.0.InternalError", "message": "The request failed due to an internal service error. The service is still operational." } } ```
This commit is to filter out those non-update-related error events from concluding the code update as failure.
The valid update-related errors are defined in - https://github.com/openbmc/phosphor-dbus-interfaces/blob/master/yaml/xyz/openbmc_project/Software/Version.errors.yaml - https://github.com/openbmc/phosphor-bmc-code-mgmt/blob/master/xyz/openbmc_project/Software/Image.errors.yaml
Tested:
1) Redfish validator passed
2) Error injection during Update.
- Start the code update and wait for completion of update (e.g. using journalctl -f)
``` $ uri=$(curl -k https://${bmc}/redfish/v1/UpdateService | jq -r ' .HttpPushUri'); echo $uri $ curl -k -H "Content-Type: application/octet-stream" -X POST -T ${image} https://${bmc}${uri} ``` - As soon as the image is untarring, and issue busctl cmd to inject a non-update error
``` busctl call xyz.openbmc_project.Logging /xyz/openbmc_project/logging \ xyz.openbmc_project.Logging.Create Create ssa{ss} \ xyz.openbmc_project.Host.Error.Event \ xyz.openbmc_project.Logging.Entry.Level.Error 1 RAWPEL \ /tmp/FILE_NBMC_UNRECOVERABLE ```
[1] https://github.com/openbmc/pldm/blob/master/oem/ibm/libpldmresponder/file_io_type_pel.cpp#L268
Change-Id: Ice54c403efacffa6a388e182bd04d97c3e2b97fc Signed-off-by: Myung Bae <myungbae@us.ibm.com>
show more ...
|
#
80f79a40
|
| 24-Aug-2023 |
Michael Shen <gpgpgp@google.com> |
Fix typo `DBusInteracesMap` -> `DBusInterfacesMap`
Change-Id: I9a851076eccee9d79ad7bb036e58b717e06ad5d1 Signed-off-by: Michael Shen <gpgpgp@google.com>
|
#
8549b951
|
| 16-Aug-2023 |
Myung Bae <myungbae@us.ibm.com> |
Refactor Update monitorForSoftwareAvailable function
The scope of this code refactor is to limit the function of monitorForSoftwareAvailable() for the coming future code modifications in the area.
Refactor Update monitorForSoftwareAvailable function
The scope of this code refactor is to limit the function of monitorForSoftwareAvailable() for the coming future code modifications in the area.
Tested: - Compiles successfully. - Code update works as before (for success and failure cases)
Change-Id: I90fd41caa6b88c97c2a0c47fcf4553d48905b886 Signed-off-by: Myung Bae <myungbae@us.ibm.com>
show more ...
|
#
bf2ddede
|
| 09-Aug-2023 |
Carson Labrado <clabrado@google.com> |
Reduce some Error log severities
There are instances of ERROR logs that would work better as WARNING or DEBUG since they do not actually result in bailing early and returning an error response.
Sig
Reduce some Error log severities
There are instances of ERROR logs that would work better as WARNING or DEBUG since they do not actually result in bailing early and returning an error response.
Signed-off-by: Carson Labrado <clabrado@google.com> Change-Id: I1e7bca0bb38487b26a4642ab72ce475170bb53c6
show more ...
|
#
1ccf70f1
|
| 02-Aug-2023 |
Myung Bae <myungbae@us.ibm.com> |
Show Update error type on logs if unknown
Update is failing due to unknown update dbus error type but the cause can not be determined as its value is not showing.
This change is to add the error ca
Show Update error type on logs if unknown
Update is failing due to unknown update dbus error type but the cause can not be determined as its value is not showing.
This change is to add the error cause to journal in addition to CRITICAL internalError.
``` Aug 02 09:00:16 bmcweb[2476]: (2023-08-02 09:00:14) [ERROR "update_service.hpp":396] Unknown Software Image Error type = <XXX> Aug 02 09:00:16 bmcweb[2476]: (2023-08-02 09:00:14) [CRITICAL "error_messages.cpp":284] Internal Error ....` ```
Not tested but successfully compiled.
Change-Id: I20833d24042bf8d2f7e2d8a8e4359e3d80af702a Signed-off-by: Myung Bae <myungbae@us.ibm.com>
show more ...
|
#
62598e31
|
| 17-Jul-2023 |
Ed Tanous <ed@tanous.net> |
Replace logging with std::format
std::format is a much more modern logging solution, and gives us a lot more flexibility, and better compile times when doing logging.
Unfortunately, given its level
Replace logging with std::format
std::format is a much more modern logging solution, and gives us a lot more flexibility, and better compile times when doing logging.
Unfortunately, given its level of compile time checks, it needs to be a method, instead of the stream style logging we had before. This requires a pretty substantial change. Fortunately, this change can be largely automated, via the script included in this commit under scripts/replace_logs.py. This is to aid people in moving their patchsets over to the new form in the short period where old patches will be based on the old logging. The intention is that this script eventually goes away.
The old style logging (stream based) looked like.
BMCWEB_LOG_DEBUG << "Foo " << foo;
The new equivalent of the above would be: BMCWEB_LOG_DEBUG("Foo {}", foo);
In the course of doing this, this also cleans up several ignored linter errors, including macro usage, and array to pointer deconstruction.
Note, This patchset does remove the timestamp from the log message. In practice, this was duplicated between journald and bmcweb, and there's no need for both to exist.
One design decision of note is the addition of logPtr. Because the compiler can't disambiguate between const char* and const MyThing*, it's necessary to add an explicit cast to void*. This is identical to how fmt handled it.
Tested: compiled with logging meson_option enabled, and launched bmcweb
Saw the usual logging, similar to what was present before: ``` [Error include/webassets.hpp:60] Unable to find or open /usr/share/www/ static file hosting disabled [Debug include/persistent_data.hpp:133] Restored Session Timeout: 1800 [Debug redfish-core/include/event_service_manager.hpp:671] Old eventService config not exist [Info src/webserver_main.cpp:59] Starting webserver on port 18080 [Error redfish-core/include/event_service_manager.hpp:1301] inotify_add_watch failed for redfish log file. [Info src/webserver_main.cpp:137] Start Hostname Monitor Service... ``` Signed-off-by: Ed Tanous <ed@tanous.net>
Change-Id: I86a46aa2454be7fe80df608cb7e5573ca4029ec8
show more ...
|
#
2c6ffdb0
|
| 28-Jun-2023 |
Ed Tanous <edtanous@google.com> |
Use openssl random number generator
We already have a generator class. We should use it. Wrap this into a function that can be unit tested, and add unit tests.
Note, some files also needed to cha
Use openssl random number generator
We already have a generator class. We should use it. Wrap this into a function that can be unit tested, and add unit tests.
Note, some files also needed to change name, because random.hpp conflicts with the built in random, and causes circular build problems. This commit changes it to ossl_random.
Tested: Unit tests pass. Now has coverage.
Redfish service validator passes.
Change-Id: I5f8eee1af5f4843a352c6fd0e26d67fd3320ef53 Signed-off-by: Ed Tanous <edtanous@google.com>
show more ...
|
#
8b24275d
|
| 27-Jun-2023 |
Ed Tanous <edtanous@google.com> |
Rename all error_code instances to ec
We're not consistent here, which leads to people copying and pasting code all over, which has lead to a bunch of different names for error codes.
This commit c
Rename all error_code instances to ec
We're not consistent here, which leads to people copying and pasting code all over, which has lead to a bunch of different names for error codes.
This commit changes to coerce them all to "ec", because that's what boost uses for a naming convention.
Tested: Rename only, code compiles.
Change-Id: I7053cc738faa9f7a82f55fc46fc78618bdf702a5 Signed-off-by: Ed Tanous <edtanous@google.com>
show more ...
|
#
9ae226fa
|
| 21-Jun-2023 |
George Liu <liuxiwei@inspur.com> |
Refactor setProperty method
SetProperty is a method we should use more, and use consistently in the codebase, this commit makes it consistently used from the utility namespace.
Tested: Refactor. C
Refactor setProperty method
SetProperty is a method we should use more, and use consistently in the codebase, this commit makes it consistently used from the utility namespace.
Tested: Refactor. Code compiles.
Signed-off-by: George Liu <liuxiwei@inspur.com> Change-Id: I5939317d23483e16bd98a8298f53e75604ef374d
show more ...
|
#
b33a4327
|
| 09-Jun-2023 |
Ninad Palsule <ninad@linux.ibm.com> |
Add content type check in the update service
The content type check is required in the update service. This may be a security issue.
The correct content types to update service are multipart/form-d
Add content type check in the update service
The content type check is required in the update service. This may be a security issue.
The correct content types to update service are multipart/form-data and application/octet-stream. The multipart content type was missing from the contentTypes array which is added in this drop.
Added couple of test cases.
Tested:
1) Make sure that update service content type application/octet-stream are working correctly. $ curl -k -H 'X-Auth-Token: THIbp1G0DiNVj3JrCZMf' -H 'Content-Type: \ application/octet-stream' -X POST \ -T ./obmc-phosphor-image-everest.ext4.mmc.tar \ https://${bmc}/redfish/v1/UpdateService/update { "@odata.id": "/redfish/v1/TaskService/Tasks/0", "@odata.type": "#Task.v1_4_3.Task", "Id": "0", "TaskState": "Running", "TaskStatus": "OK"
2) Make sure that update service content type multipart/form-data are working correctly. $ curl -k -H 'X-Auth-Token: Vc7KBgM6z3uMs1G7uVqu' \ -H Content-Type:multipart/form-data \ -F 'UpdateParameters={"Targets":["/redfish/v1/Managers/bmc"], \ "@Redfish.OperationApplyTime":"Immediate"};type=application/json'\ -F 'UpdateFile=@obmc-phosphor-image-p10bmc.ext4.mmc.tar; \ type=application/octet-stream' \ https://${bmc}/redfish/v1/UpdateService/update { "@Message.ExtendedInfo": [ { "@odata.type": "#Message.v1_1_1.Message", "Message": "The request completed successfully.", "MessageArgs": [], "MessageId": "Base.1.16.0.Success", "MessageSeverity": "OK", "Resolution": "None" } ], "@odata.id": "/redfish/v1/TaskService/Tasks/0", "@odata.type": "#Task.v1_4_3.Task", "Id": "0", "TaskState": "Running", "TaskStatus": "OK"
3) Make sure that command fails when content type is missing. $ curl -k -H 'X-Auth-Token: vH3B88sh323sfy0YG8eN' -H Content-Type: \ -X POST -T ./obmc-phosphor-image-everest.ext4.mmc.tar \ https://${bmc}/redfish/v1/UpdateService/update Bad Request
[INFO "http_connection.hpp":201] Request: 0x177f920 HTTP/1.1 POST \ /redfish/v1/UpdateService/update ::ffff:x.x.xx.xxx | [DEBUG "update_service.hpp":687] doPost: contentType= [DEBUG "update_service.hpp":692] Bad content type specified:
4) Make sure that command fails when wrong cotent type specified. $ curl -k -H 'X-Auth-Token: OQzODMaR0G29AjpD2YmT' -H 'Content-Type: \ application/octet-json' -X POST \ -T ./obmc-phosphor-image-everest.ext4.mmc.tar \ https://${bmc}/redfish/v1/UpdateService/update Bad Request
[INFO "http_connection.hpp":201] Request: 0x17a69d0 HTTP/1.1 POST \ /redfish/v1/UpdateService/update ::ffff:x.x.xx.xxx | [DEBUG "update_service.hpp":687] doPost: contentType=application/octet-json [DEBUG "update_service.hpp":720] Bad content type specified: application/octet-json
5) Make sure that command fails when header is not specified. $ curl -k -H 'X-Auth-Token: Z1AEXg075qGKi0xISu6o' -X POST \ -T ./obmc-phosphor-image-everest.ext4.mmc.tar \ https://${bmc}/redfish/v1/UpdateService/update Bad Request
[INFO "http_connection.hpp":201] Request: 0x17a69d0 HTTP/1.1 \ POST /redfish/v1/UpdateService/update ::ffff:x.x.xx.xxx | [DEBUG "update_service.hpp":687] doPost: contentType= [DEBUG "update_service.hpp":692] Bad content type specified:
Change-Id: I48b709b6219debfed9ff60dd46ab87652e5a1fe5 Signed-off-by: Ninad Palsule <ninad@linux.ibm.com>
show more ...
|
#
b90d14f2
|
| 31-May-2023 |
Myung Bae <myungbae@us.ibm.com> |
Fix Error log entries to Warning
Some logging entries are categorized as ERROR, but they would better be as WARNING.
1) ``` $ curl -k -X GET https://${bmc}:18080/redfish/v1/Managers/bmc/LogServices
Fix Error log entries to Warning
Some logging entries are categorized as ERROR, but they would better be as WARNING.
1) ``` $ curl -k -X GET https://${bmc}:18080/redfish/v1/Managers/bmc/LogServices/Dump/Entries/INVALID { .... "code": "Base.1.13.0.InternalError", "message": "The request failed due to an internal service error. The service is still operational." } }%
(2023-06-01 23:29:40) [ERROR "log_services.hpp":665] Can't find Dump Entry (2023-06-01 23:29:40) [CRITICAL "error_messages.cpp":282] Internal Error \ ../../../../../../../../../bmcweb/redfish-core/lib/log_services.hpp(666:36) \ `redfish::getDumpEntryById(const std::shared_ptr<bmcweb::AsyncResp>&, const std::string&, \ const std::string&)::<lambda(const boost::system::error_code&, const dbus::utility::ManagedObjectType&)>`: ```
2) ``` $ curl -k -X GET https://${bmc}:18080/redfish/v1/UpdateService/FirmwareInventory/INVALID
(2023-05-31 15:03:38) [ERROR "update_service.hpp":1010] Input swID X1cd6ce5fZ not found! ```
Tested: - Set bmcweb-logging=error to obtain Error or higher logs - Run the above commands and watch out logs - Redfish validator passed and see whether there are unexpected error or higher level logs
Change-Id: I5f14eedd68fd3454cdf2a5b2f34442a7718e718a Signed-off-by: Myung Bae <myungbae@us.ibm.com>
show more ...
|
#
ac106bf6
|
| 07-Jun-2023 |
Ed Tanous <edtanous@google.com> |
Consistently name AsyncResp variables
In about half of our code, AsyncResp objects take the name asyncResp, and in the other half they take the name aResp. While the difference between them is negl
Consistently name AsyncResp variables
In about half of our code, AsyncResp objects take the name asyncResp, and in the other half they take the name aResp. While the difference between them is negligeble and arbitrary, having two naming conventions makes it more difficult to do automated changes over time via grep.
This commit was generated automtatically with the command: git grep -l 'aResp' | xargs sed -i 's|aResp|asyncResp|g'
Tested: Code compiles.
Change-Id: Id363437b6a78f51e91cbf60aa0a0c2286f36a037 Signed-off-by: Ed Tanous <edtanous@google.com>
show more ...
|
#
08d81ada
|
| 17-May-2022 |
John Edward Broadbent <jebr@google.com> |
update service: use getCollectionMembers
There are some cases that getCollectionMembers can be leveraged
Tested:
GET https://127.0.0.1:443/redfish/v1/UpdateService/FirmwareInventory/ Returns the s
update service: use getCollectionMembers
There are some cases that getCollectionMembers can be leveraged
Tested:
GET https://127.0.0.1:443/redfish/v1/UpdateService/FirmwareInventory/ Returns the same result.
Redfish service validator passes.
Signed-off-by: John Edward Broadbent <jebr@google.com> Change-Id: I417bc08cffd24c6c95abaf86013002ce705d20a4
show more ...
|
#
81c4e330
|
| 18-May-2023 |
Ed Tanous <edtanous@google.com> |
Capture all boost::system::error_codes by ref
Capturing these possibly overloaded values by reference can avoid a copy in some cases, and it's good to be consistent.
This change was made automatica
Capture all boost::system::error_codes by ref
Capturing these possibly overloaded values by reference can avoid a copy in some cases, and it's good to be consistent.
This change was made automatically by grep/sed.
Tested: Code compiles.
Signed-off-by: Ed Tanous <edtanous@google.com> Change-Id: Iafeaca2a5dc52f39753b5a3880419d6bc943f81b
show more ...
|
#
4a40441f
|
| 15-May-2023 |
Ed Tanous <edtanous@google.com> |
Remove redfish-post-to-old-updateservice
It is now Q2 2023, and this option has been deprecated. Maintainers have not had any reports of this behavior breaking people.
Tested: Code delete only. C
Remove redfish-post-to-old-updateservice
It is now Q2 2023, and this option has been deprecated. Maintainers have not had any reports of this behavior breaking people.
Tested: Code delete only. Code compiles.
Change-Id: I9c1fe26e497806c6bc602fb019bafe0fc80d7619 Signed-off-by: Ed Tanous <edtanous@google.com>
show more ...
|
#
ef4c65b7
|
| 24-Apr-2023 |
Ed Tanous <edtanous@google.com> |
Boost::urls::format
Boost 1.82 dropped a lovely new toy, boost::urls::format, which is a lot like our urlFromPieces method, but better in that it makes the resulting uris more readable, and allows d
Boost::urls::format
Boost 1.82 dropped a lovely new toy, boost::urls::format, which is a lot like our urlFromPieces method, but better in that it makes the resulting uris more readable, and allows doing things like fragments in a single line instead of multiple. We should prefer it in some cases.
Tested: Redfish service validator passes. Spot checks of URLs work as expected. Unit tests pass.
Signed-off-by: Ed Tanous <edtanous@google.com> Change-Id: Ia7b38f0a95771c862507e7d5b4aa68aa1c98403c
show more ...
|
#
b2ba3072
|
| 12-May-2023 |
Patrick Williams <patrick@stwcx.xyz> |
fix more push vs emplace calls
It seems like clang-tidy doesn't catch every place that an emplace could be used instead of a push. Use a few grep/sed pairs to find and fix up some common patterns.
fix more push vs emplace calls
It seems like clang-tidy doesn't catch every place that an emplace could be used instead of a push. Use a few grep/sed pairs to find and fix up some common patterns.
Signed-off-by: Patrick Williams <patrick@stwcx.xyz> Change-Id: I93eaec26b8e3be240599e92b66cf54947073dc4c
show more ...
|
#
89492a15
|
| 10-May-2023 |
Patrick Williams <patrick@stwcx.xyz> |
clang-format: copy latest and re-format
clang-format-16 has some backwards incompatible changes that require additional settings for best compatibility and re-running the formatter. Copy the latest
clang-format: copy latest and re-format
clang-format-16 has some backwards incompatible changes that require additional settings for best compatibility and re-running the formatter. Copy the latest .clang-format from the docs repository and reformat the repository.
Change-Id: I75f89d2959b0f1338c20d72ad669fbdc1d720835 Signed-off-by: Patrick Williams <patrick@stwcx.xyz>
show more ...
|
#
0ed80c8c
|
| 12-May-2020 |
George Liu <liuxiwei@inspur.com> |
UpdateService: Support for MultipartHttpPushUri
Since a service support the MultipartHttpPushUri property within the UpdateService resource, so add a new MultipartHttpPushUri property, This property
UpdateService: Support for MultipartHttpPushUri
Since a service support the MultipartHttpPushUri property within the UpdateService resource, so add a new MultipartHttpPushUri property, This property shall contain a URI used to perform a Redfish Specification-defined Multipart HTTP or HTTPS POST of a software image for the purpose of installing software contained within the image, and use the requirements of a multipart/form-data to request body for HTTP push software update.
Tested: curl -k -H "X-Auth-Token: $token" -H "Content-Type: multipart/form-data" -F 'UpdateParameters={"Targets":["/redfish/v1/Managers/bmc"], "@Redfish.OperationApplyTime":"Immediate"};type=application/json' -F 'UpdateFile=@obmc-phosphor-image.static.mtd.tar;type=application/ octet-stream' https://${bmc}/redfish/v1/UpdateService/update { "@odata.id": "/redfish/v1/TaskService/Tasks/0", "@odata.type": "#Task.v1_4_3.Task", "Id": "0", "TaskState": "Running", "TaskStatus": "OK" }
Passed the validator:
Signed-off-by: George Liu <liuxiwei@inspur.com> Change-Id: Ie1ea0594337efdb073270aba6918389c4381a2b3
show more ...
|
#
33c6b580
|
| 14-Feb-2023 |
Ed Tanous <edtanous@google.com> |
Remove body member from Request
Per cpp core guidelines, these should be methods.
Tested: on last patchset of the series.
Signed-off-by: Ed Tanous <edtanous@google.com> Change-Id: Ib16479db9d2b68d
Remove body member from Request
Per cpp core guidelines, these should be methods.
Tested: on last patchset of the series.
Signed-off-by: Ed Tanous <edtanous@google.com> Change-Id: Ib16479db9d2b68da68e7ad6e825c7e205c64f1de
show more ...
|
#
5e7e2dc5
|
| 16-Feb-2023 |
Ed Tanous <edtanous@google.com> |
Take boost error_code by reference
By convention, we should be following boost here, and passing error_code by reference, not by value. This makes our code consistent, and removes the need for a co
Take boost error_code by reference
By convention, we should be following boost here, and passing error_code by reference, not by value. This makes our code consistent, and removes the need for a copy in some cases.
Signed-off-by: Ed Tanous <edtanous@google.com> Change-Id: Id42ea4a90b6685a84818b87d1506c11256b3b9ae
show more ...
|
#
eddfc437
|
| 26-Sep-2022 |
Willy Tu <wltu@google.com> |
Update most resources to use urlFromPieces
Only id in event_service and account_service have not been updated due to the risk of it breaking the username/id. It will require further testing to verif
Update most resources to use urlFromPieces
Only id in event_service and account_service have not been updated due to the risk of it breaking the username/id. It will require further testing to verify.
Use urlFromPieces wherever that is needed to insert a variable in the URI. Don't use urlFromPieces when it is hardcoded values. This allow us to control all resource URIs that is dynamically added and to sync with the current recommanded method for `@odata.id`. The goal is to have a common place to manage the url created from dbus-paths in order to manage/update it easily when needed.
Tested: RedfishValidtor Passed for all resource including the sensors with the fragments.
Change-Id: I95cdfaaee58fc7f21c95f5944e1e5c813b3215f2 Signed-off-by: Willy Tu <wltu@google.com> Signed-off-by: Ed Tanous <edtanous@google.com>
show more ...
|