diff options
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/lru_cache.c | 9 | ||||
| -rw-r--r-- | lib/string_helpers.c | 193 | ||||
| -rw-r--r-- | lib/test-hexdump.c | 8 | ||||
| -rw-r--r-- | lib/test-string_helpers.c | 40 | ||||
| -rw-r--r-- | lib/vsprintf.c | 110 |
5 files changed, 181 insertions, 179 deletions
diff --git a/lib/lru_cache.c b/lib/lru_cache.c index 852c81e3ba9a..028f5d996eef 100644 --- a/lib/lru_cache.c +++ b/lib/lru_cache.c | |||
| @@ -247,10 +247,11 @@ size_t lc_seq_printf_stats(struct seq_file *seq, struct lru_cache *lc) | |||
| 247 | * progress) and "changed", when this in fact lead to an successful | 247 | * progress) and "changed", when this in fact lead to an successful |
| 248 | * update of the cache. | 248 | * update of the cache. |
| 249 | */ | 249 | */ |
| 250 | return seq_printf(seq, "\t%s: used:%u/%u " | 250 | seq_printf(seq, "\t%s: used:%u/%u hits:%lu misses:%lu starving:%lu locked:%lu changed:%lu\n", |
| 251 | "hits:%lu misses:%lu starving:%lu locked:%lu changed:%lu\n", | 251 | lc->name, lc->used, lc->nr_elements, |
| 252 | lc->name, lc->used, lc->nr_elements, | 252 | lc->hits, lc->misses, lc->starving, lc->locked, lc->changed); |
| 253 | lc->hits, lc->misses, lc->starving, lc->locked, lc->changed); | 253 | |
| 254 | return 0; | ||
| 254 | } | 255 | } |
| 255 | 256 | ||
| 256 | static struct hlist_head *lc_hash_slot(struct lru_cache *lc, unsigned int enr) | 257 | static struct hlist_head *lc_hash_slot(struct lru_cache *lc, unsigned int enr) |
diff --git a/lib/string_helpers.c b/lib/string_helpers.c index 8f8c4417f228..1826c7407258 100644 --- a/lib/string_helpers.c +++ b/lib/string_helpers.c | |||
| @@ -239,29 +239,21 @@ int string_unescape(char *src, char *dst, size_t size, unsigned int flags) | |||
| 239 | } | 239 | } |
| 240 | EXPORT_SYMBOL(string_unescape); | 240 | EXPORT_SYMBOL(string_unescape); |
| 241 | 241 | ||
| 242 | static int escape_passthrough(unsigned char c, char **dst, size_t *osz) | 242 | static bool escape_passthrough(unsigned char c, char **dst, char *end) |
| 243 | { | 243 | { |
| 244 | char *out = *dst; | 244 | char *out = *dst; |
| 245 | 245 | ||
| 246 | if (*osz < 1) | 246 | if (out < end) |
| 247 | return -ENOMEM; | 247 | *out = c; |
| 248 | 248 | *dst = out + 1; | |
| 249 | *out++ = c; | 249 | return true; |
| 250 | |||
| 251 | *dst = out; | ||
| 252 | *osz -= 1; | ||
| 253 | |||
| 254 | return 1; | ||
| 255 | } | 250 | } |
| 256 | 251 | ||
| 257 | static int escape_space(unsigned char c, char **dst, size_t *osz) | 252 | static bool escape_space(unsigned char c, char **dst, char *end) |
| 258 | { | 253 | { |
| 259 | char *out = *dst; | 254 | char *out = *dst; |
| 260 | unsigned char to; | 255 | unsigned char to; |
| 261 | 256 | ||
| 262 | if (*osz < 2) | ||
| 263 | return -ENOMEM; | ||
| 264 | |||
| 265 | switch (c) { | 257 | switch (c) { |
| 266 | case '\n': | 258 | case '\n': |
| 267 | to = 'n'; | 259 | to = 'n'; |
| @@ -279,26 +271,25 @@ static int escape_space(unsigned char c, char **dst, size_t *osz) | |||
| 279 | to = 'f'; | 271 | to = 'f'; |
| 280 | break; | 272 | break; |
| 281 | default: | 273 | default: |
| 282 | return 0; | 274 | return false; |
| 283 | } | 275 | } |
| 284 | 276 | ||
| 285 | *out++ = '\\'; | 277 | if (out < end) |
| 286 | *out++ = to; | 278 | *out = '\\'; |
| 279 | ++out; | ||
| 280 | if (out < end) | ||
| 281 | *out = to; | ||
| 282 | ++out; | ||
| 287 | 283 | ||
| 288 | *dst = out; | 284 | *dst = out; |
| 289 | *osz -= 2; | 285 | return true; |
| 290 | |||
| 291 | return 1; | ||
| 292 | } | 286 | } |
| 293 | 287 | ||
| 294 | static int escape_special(unsigned char c, char **dst, size_t *osz) | 288 | static bool escape_special(unsigned char c, char **dst, char *end) |
| 295 | { | 289 | { |
| 296 | char *out = *dst; | 290 | char *out = *dst; |
| 297 | unsigned char to; | 291 | unsigned char to; |
| 298 | 292 | ||
| 299 | if (*osz < 2) | ||
| 300 | return -ENOMEM; | ||
| 301 | |||
| 302 | switch (c) { | 293 | switch (c) { |
| 303 | case '\\': | 294 | case '\\': |
| 304 | to = '\\'; | 295 | to = '\\'; |
| @@ -310,71 +301,78 @@ static int escape_special(unsigned char c, char **dst, size_t *osz) | |||
| 310 | to = 'e'; | 301 | to = 'e'; |
| 311 | break; | 302 | break; |
| 312 | default: | 303 | default: |
| 313 | return 0; | 304 | return false; |
| 314 | } | 305 | } |
| 315 | 306 | ||
| 316 | *out++ = '\\'; | 307 | if (out < end) |
| 317 | *out++ = to; | 308 | *out = '\\'; |
| 309 | ++out; | ||
| 310 | if (out < end) | ||
| 311 | *out = to; | ||
| 312 | ++out; | ||
| 318 | 313 | ||
| 319 | *dst = out; | 314 | *dst = out; |
| 320 | *osz -= 2; | 315 | return true; |
| 321 | |||
| 322 | return 1; | ||
| 323 | } | 316 | } |
| 324 | 317 | ||
| 325 | static int escape_null(unsigned char c, char **dst, size_t *osz) | 318 | static bool escape_null(unsigned char c, char **dst, char *end) |
| 326 | { | 319 | { |
| 327 | char *out = *dst; | 320 | char *out = *dst; |
| 328 | 321 | ||
| 329 | if (*osz < 2) | ||
| 330 | return -ENOMEM; | ||
| 331 | |||
| 332 | if (c) | 322 | if (c) |
| 333 | return 0; | 323 | return false; |
| 334 | 324 | ||
| 335 | *out++ = '\\'; | 325 | if (out < end) |
| 336 | *out++ = '0'; | 326 | *out = '\\'; |
| 327 | ++out; | ||
| 328 | if (out < end) | ||
| 329 | *out = '0'; | ||
| 330 | ++out; | ||
| 337 | 331 | ||
| 338 | *dst = out; | 332 | *dst = out; |
| 339 | *osz -= 2; | 333 | return true; |
| 340 | |||
| 341 | return 1; | ||
| 342 | } | 334 | } |
| 343 | 335 | ||
| 344 | static int escape_octal(unsigned char c, char **dst, size_t *osz) | 336 | static bool escape_octal(unsigned char c, char **dst, char *end) |
| 345 | { | 337 | { |
| 346 | char *out = *dst; | 338 | char *out = *dst; |
| 347 | 339 | ||
| 348 | if (*osz < 4) | 340 | if (out < end) |
| 349 | return -ENOMEM; | 341 | *out = '\\'; |
| 350 | 342 | ++out; | |
| 351 | *out++ = '\\'; | 343 | if (out < end) |
| 352 | *out++ = ((c >> 6) & 0x07) + '0'; | 344 | *out = ((c >> 6) & 0x07) + '0'; |
| 353 | *out++ = ((c >> 3) & 0x07) + '0'; | 345 | ++out; |
| 354 | *out++ = ((c >> 0) & 0x07) + '0'; | 346 | if (out < end) |
| 347 | *out = ((c >> 3) & 0x07) + '0'; | ||
| 348 | ++out; | ||
| 349 | if (out < end) | ||
| 350 | *out = ((c >> 0) & 0x07) + '0'; | ||
| 351 | ++out; | ||
| 355 | 352 | ||
| 356 | *dst = out; | 353 | *dst = out; |
| 357 | *osz -= 4; | 354 | return true; |
| 358 | |||
| 359 | return 1; | ||
| 360 | } | 355 | } |
| 361 | 356 | ||
| 362 | static int escape_hex(unsigned char c, char **dst, size_t *osz) | 357 | static bool escape_hex(unsigned char c, char **dst, char *end) |
| 363 | { | 358 | { |
| 364 | char *out = *dst; | 359 | char *out = *dst; |
| 365 | 360 | ||
| 366 | if (*osz < 4) | 361 | if (out < end) |
| 367 | return -ENOMEM; | 362 | *out = '\\'; |
| 368 | 363 | ++out; | |
| 369 | *out++ = '\\'; | 364 | if (out < end) |
| 370 | *out++ = 'x'; | 365 | *out = 'x'; |
| 371 | *out++ = hex_asc_hi(c); | 366 | ++out; |
| 372 | *out++ = hex_asc_lo(c); | 367 | if (out < end) |
| 368 | *out = hex_asc_hi(c); | ||
| 369 | ++out; | ||
| 370 | if (out < end) | ||
| 371 | *out = hex_asc_lo(c); | ||
| 372 | ++out; | ||
| 373 | 373 | ||
| 374 | *dst = out; | 374 | *dst = out; |
| 375 | *osz -= 4; | 375 | return true; |
| 376 | |||
| 377 | return 1; | ||
| 378 | } | 376 | } |
| 379 | 377 | ||
| 380 | /** | 378 | /** |
| @@ -426,19 +424,17 @@ static int escape_hex(unsigned char c, char **dst, size_t *osz) | |||
| 426 | * it if needs. | 424 | * it if needs. |
| 427 | * | 425 | * |
| 428 | * Return: | 426 | * Return: |
| 429 | * The amount of the characters processed to the destination buffer, or | 427 | * The total size of the escaped output that would be generated for |
| 430 | * %-ENOMEM if the size of buffer is not enough to put an escaped character is | 428 | * the given input and flags. To check whether the output was |
| 431 | * returned. | 429 | * truncated, compare the return value to osz. There is room left in |
| 432 | * | 430 | * dst for a '\0' terminator if and only if ret < osz. |
| 433 | * Even in the case of error @dst pointer will be updated to point to the byte | ||
| 434 | * after the last processed character. | ||
| 435 | */ | 431 | */ |
| 436 | int string_escape_mem(const char *src, size_t isz, char **dst, size_t osz, | 432 | int string_escape_mem(const char *src, size_t isz, char *dst, size_t osz, |
| 437 | unsigned int flags, const char *esc) | 433 | unsigned int flags, const char *esc) |
| 438 | { | 434 | { |
| 439 | char *out = *dst, *p = out; | 435 | char *p = dst; |
| 436 | char *end = p + osz; | ||
| 440 | bool is_dict = esc && *esc; | 437 | bool is_dict = esc && *esc; |
| 441 | int ret = 0; | ||
| 442 | 438 | ||
| 443 | while (isz--) { | 439 | while (isz--) { |
| 444 | unsigned char c = *src++; | 440 | unsigned char c = *src++; |
| @@ -458,55 +454,26 @@ int string_escape_mem(const char *src, size_t isz, char **dst, size_t osz, | |||
| 458 | (is_dict && !strchr(esc, c))) { | 454 | (is_dict && !strchr(esc, c))) { |
| 459 | /* do nothing */ | 455 | /* do nothing */ |
| 460 | } else { | 456 | } else { |
| 461 | if (flags & ESCAPE_SPACE) { | 457 | if (flags & ESCAPE_SPACE && escape_space(c, &p, end)) |
| 462 | ret = escape_space(c, &p, &osz); | 458 | continue; |
| 463 | if (ret < 0) | 459 | |
| 464 | break; | 460 | if (flags & ESCAPE_SPECIAL && escape_special(c, &p, end)) |
| 465 | if (ret > 0) | 461 | continue; |
| 466 | continue; | 462 | |
| 467 | } | 463 | if (flags & ESCAPE_NULL && escape_null(c, &p, end)) |
| 468 | 464 | continue; | |
| 469 | if (flags & ESCAPE_SPECIAL) { | ||
| 470 | ret = escape_special(c, &p, &osz); | ||
| 471 | if (ret < 0) | ||
| 472 | break; | ||
| 473 | if (ret > 0) | ||
| 474 | continue; | ||
| 475 | } | ||
| 476 | |||
| 477 | if (flags & ESCAPE_NULL) { | ||
| 478 | ret = escape_null(c, &p, &osz); | ||
| 479 | if (ret < 0) | ||
| 480 | break; | ||
| 481 | if (ret > 0) | ||
| 482 | continue; | ||
| 483 | } | ||
| 484 | 465 | ||
| 485 | /* ESCAPE_OCTAL and ESCAPE_HEX always go last */ | 466 | /* ESCAPE_OCTAL and ESCAPE_HEX always go last */ |
| 486 | if (flags & ESCAPE_OCTAL) { | 467 | if (flags & ESCAPE_OCTAL && escape_octal(c, &p, end)) |
| 487 | ret = escape_octal(c, &p, &osz); | ||
| 488 | if (ret < 0) | ||
| 489 | break; | ||
| 490 | continue; | 468 | continue; |
| 491 | } | 469 | |
| 492 | if (flags & ESCAPE_HEX) { | 470 | if (flags & ESCAPE_HEX && escape_hex(c, &p, end)) |
| 493 | ret = escape_hex(c, &p, &osz); | ||
| 494 | if (ret < 0) | ||
| 495 | break; | ||
| 496 | continue; | 471 | continue; |
| 497 | } | ||
| 498 | } | 472 | } |
| 499 | 473 | ||
| 500 | ret = escape_passthrough(c, &p, &osz); | 474 | escape_passthrough(c, &p, end); |
| 501 | if (ret < 0) | ||
| 502 | break; | ||
| 503 | } | 475 | } |
| 504 | 476 | ||
| 505 | *dst = p; | 477 | return p - dst; |
| 506 | |||
| 507 | if (ret < 0) | ||
| 508 | return ret; | ||
| 509 | |||
| 510 | return p - out; | ||
| 511 | } | 478 | } |
| 512 | EXPORT_SYMBOL(string_escape_mem); | 479 | EXPORT_SYMBOL(string_escape_mem); |
diff --git a/lib/test-hexdump.c b/lib/test-hexdump.c index daf29a390a89..9846ff7428b3 100644 --- a/lib/test-hexdump.c +++ b/lib/test-hexdump.c | |||
| @@ -18,26 +18,26 @@ static const unsigned char data_b[] = { | |||
| 18 | 18 | ||
| 19 | static const unsigned char data_a[] = ".2.{....p..$}.4...1.....L...C..."; | 19 | static const unsigned char data_a[] = ".2.{....p..$}.4...1.....L...C..."; |
| 20 | 20 | ||
| 21 | static const char *test_data_1_le[] __initconst = { | 21 | static const char * const test_data_1_le[] __initconst = { |
| 22 | "be", "32", "db", "7b", "0a", "18", "93", "b2", | 22 | "be", "32", "db", "7b", "0a", "18", "93", "b2", |
| 23 | "70", "ba", "c4", "24", "7d", "83", "34", "9b", | 23 | "70", "ba", "c4", "24", "7d", "83", "34", "9b", |
| 24 | "a6", "9c", "31", "ad", "9c", "0f", "ac", "e9", | 24 | "a6", "9c", "31", "ad", "9c", "0f", "ac", "e9", |
| 25 | "4c", "d1", "19", "99", "43", "b1", "af", "0c", | 25 | "4c", "d1", "19", "99", "43", "b1", "af", "0c", |
| 26 | }; | 26 | }; |
| 27 | 27 | ||
| 28 | static const char *test_data_2_le[] __initconst = { | 28 | static const char *test_data_2_le[] __initdata = { |
| 29 | "32be", "7bdb", "180a", "b293", | 29 | "32be", "7bdb", "180a", "b293", |
| 30 | "ba70", "24c4", "837d", "9b34", | 30 | "ba70", "24c4", "837d", "9b34", |
| 31 | "9ca6", "ad31", "0f9c", "e9ac", | 31 | "9ca6", "ad31", "0f9c", "e9ac", |
| 32 | "d14c", "9919", "b143", "0caf", | 32 | "d14c", "9919", "b143", "0caf", |
| 33 | }; | 33 | }; |
| 34 | 34 | ||
| 35 | static const char *test_data_4_le[] __initconst = { | 35 | static const char *test_data_4_le[] __initdata = { |
| 36 | "7bdb32be", "b293180a", "24c4ba70", "9b34837d", | 36 | "7bdb32be", "b293180a", "24c4ba70", "9b34837d", |
| 37 | "ad319ca6", "e9ac0f9c", "9919d14c", "0cafb143", | 37 | "ad319ca6", "e9ac0f9c", "9919d14c", "0cafb143", |
| 38 | }; | 38 | }; |
| 39 | 39 | ||
| 40 | static const char *test_data_8_le[] __initconst = { | 40 | static const char *test_data_8_le[] __initdata = { |
| 41 | "b293180a7bdb32be", "9b34837d24c4ba70", | 41 | "b293180a7bdb32be", "9b34837d24c4ba70", |
| 42 | "e9ac0f9cad319ca6", "0cafb1439919d14c", | 42 | "e9ac0f9cad319ca6", "0cafb1439919d14c", |
| 43 | }; | 43 | }; |
diff --git a/lib/test-string_helpers.c b/lib/test-string_helpers.c index ab0d30e1e18f..8e376efd88a4 100644 --- a/lib/test-string_helpers.c +++ b/lib/test-string_helpers.c | |||
| @@ -260,16 +260,28 @@ static __init const char *test_string_find_match(const struct test_string_2 *s2, | |||
| 260 | return NULL; | 260 | return NULL; |
| 261 | } | 261 | } |
| 262 | 262 | ||
| 263 | static __init void | ||
| 264 | test_string_escape_overflow(const char *in, int p, unsigned int flags, const char *esc, | ||
| 265 | int q_test, const char *name) | ||
| 266 | { | ||
| 267 | int q_real; | ||
| 268 | |||
| 269 | q_real = string_escape_mem(in, p, NULL, 0, flags, esc); | ||
| 270 | if (q_real != q_test) | ||
| 271 | pr_warn("Test '%s' failed: flags = %u, osz = 0, expected %d, got %d\n", | ||
| 272 | name, flags, q_test, q_real); | ||
| 273 | } | ||
| 274 | |||
| 263 | static __init void test_string_escape(const char *name, | 275 | static __init void test_string_escape(const char *name, |
| 264 | const struct test_string_2 *s2, | 276 | const struct test_string_2 *s2, |
| 265 | unsigned int flags, const char *esc) | 277 | unsigned int flags, const char *esc) |
| 266 | { | 278 | { |
| 267 | int q_real = 512; | 279 | size_t out_size = 512; |
| 268 | char *out_test = kmalloc(q_real, GFP_KERNEL); | 280 | char *out_test = kmalloc(out_size, GFP_KERNEL); |
| 269 | char *out_real = kmalloc(q_real, GFP_KERNEL); | 281 | char *out_real = kmalloc(out_size, GFP_KERNEL); |
| 270 | char *in = kmalloc(256, GFP_KERNEL); | 282 | char *in = kmalloc(256, GFP_KERNEL); |
| 271 | char *buf = out_real; | ||
| 272 | int p = 0, q_test = 0; | 283 | int p = 0, q_test = 0; |
| 284 | int q_real; | ||
| 273 | 285 | ||
| 274 | if (!out_test || !out_real || !in) | 286 | if (!out_test || !out_real || !in) |
| 275 | goto out; | 287 | goto out; |
| @@ -301,29 +313,19 @@ static __init void test_string_escape(const char *name, | |||
| 301 | q_test += len; | 313 | q_test += len; |
| 302 | } | 314 | } |
| 303 | 315 | ||
| 304 | q_real = string_escape_mem(in, p, &buf, q_real, flags, esc); | 316 | q_real = string_escape_mem(in, p, out_real, out_size, flags, esc); |
| 305 | 317 | ||
| 306 | test_string_check_buf(name, flags, in, p, out_real, q_real, out_test, | 318 | test_string_check_buf(name, flags, in, p, out_real, q_real, out_test, |
| 307 | q_test); | 319 | q_test); |
| 320 | |||
| 321 | test_string_escape_overflow(in, p, flags, esc, q_test, name); | ||
| 322 | |||
| 308 | out: | 323 | out: |
| 309 | kfree(in); | 324 | kfree(in); |
| 310 | kfree(out_real); | 325 | kfree(out_real); |
| 311 | kfree(out_test); | 326 | kfree(out_test); |
| 312 | } | 327 | } |
| 313 | 328 | ||
| 314 | static __init void test_string_escape_nomem(void) | ||
| 315 | { | ||
| 316 | char *in = "\eb \\C\007\"\x90\r]"; | ||
| 317 | char out[64], *buf = out; | ||
| 318 | int rc = -ENOMEM, ret; | ||
| 319 | |||
| 320 | ret = string_escape_str_any_np(in, &buf, strlen(in), NULL); | ||
| 321 | if (ret == rc) | ||
| 322 | return; | ||
| 323 | |||
| 324 | pr_err("Test 'escape nomem' failed: got %d instead of %d\n", ret, rc); | ||
| 325 | } | ||
| 326 | |||
| 327 | static int __init test_string_helpers_init(void) | 329 | static int __init test_string_helpers_init(void) |
| 328 | { | 330 | { |
| 329 | unsigned int i; | 331 | unsigned int i; |
| @@ -342,8 +344,6 @@ static int __init test_string_helpers_init(void) | |||
| 342 | for (i = 0; i < (ESCAPE_ANY_NP | ESCAPE_HEX) + 1; i++) | 344 | for (i = 0; i < (ESCAPE_ANY_NP | ESCAPE_HEX) + 1; i++) |
| 343 | test_string_escape("escape 1", escape1, i, TEST_STRING_2_DICT_1); | 345 | test_string_escape("escape 1", escape1, i, TEST_STRING_2_DICT_1); |
| 344 | 346 | ||
| 345 | test_string_escape_nomem(); | ||
| 346 | |||
| 347 | return -EINVAL; | 347 | return -EINVAL; |
| 348 | } | 348 | } |
| 349 | module_init(test_string_helpers_init); | 349 | module_init(test_string_helpers_init); |
diff --git a/lib/vsprintf.c b/lib/vsprintf.c index b235c96167d3..3a1e0843f9a2 100644 --- a/lib/vsprintf.c +++ b/lib/vsprintf.c | |||
| @@ -17,6 +17,7 @@ | |||
| 17 | */ | 17 | */ |
| 18 | 18 | ||
| 19 | #include <stdarg.h> | 19 | #include <stdarg.h> |
| 20 | #include <linux/clk-provider.h> | ||
| 20 | #include <linux/module.h> /* for KSYM_SYMBOL_LEN */ | 21 | #include <linux/module.h> /* for KSYM_SYMBOL_LEN */ |
| 21 | #include <linux/types.h> | 22 | #include <linux/types.h> |
| 22 | #include <linux/string.h> | 23 | #include <linux/string.h> |
| @@ -340,11 +341,11 @@ int num_to_str(char *buf, int size, unsigned long long num) | |||
| 340 | return len; | 341 | return len; |
| 341 | } | 342 | } |
| 342 | 343 | ||
| 343 | #define ZEROPAD 1 /* pad with zero */ | 344 | #define SIGN 1 /* unsigned/signed, must be 1 */ |
| 344 | #define SIGN 2 /* unsigned/signed long */ | 345 | #define LEFT 2 /* left justified */ |
| 345 | #define PLUS 4 /* show plus */ | 346 | #define PLUS 4 /* show plus */ |
| 346 | #define SPACE 8 /* space if plus */ | 347 | #define SPACE 8 /* space if plus */ |
| 347 | #define LEFT 16 /* left justified */ | 348 | #define ZEROPAD 16 /* pad with zero, must be 16 == '0' - ' ' */ |
| 348 | #define SMALL 32 /* use lowercase in hex (must be 32 == 0x20) */ | 349 | #define SMALL 32 /* use lowercase in hex (must be 32 == 0x20) */ |
| 349 | #define SPECIAL 64 /* prefix hex with "0x", octal with "0" */ | 350 | #define SPECIAL 64 /* prefix hex with "0x", octal with "0" */ |
| 350 | 351 | ||
| @@ -383,10 +384,7 @@ static noinline_for_stack | |||
| 383 | char *number(char *buf, char *end, unsigned long long num, | 384 | char *number(char *buf, char *end, unsigned long long num, |
| 384 | struct printf_spec spec) | 385 | struct printf_spec spec) |
| 385 | { | 386 | { |
| 386 | /* we are called with base 8, 10 or 16, only, thus don't need "G..." */ | 387 | char tmp[3 * sizeof(num)]; |
| 387 | static const char digits[16] = "0123456789ABCDEF"; /* "GHIJKLMNOPQRSTUVWXYZ"; */ | ||
| 388 | |||
| 389 | char tmp[66]; | ||
| 390 | char sign; | 388 | char sign; |
| 391 | char locase; | 389 | char locase; |
| 392 | int need_pfx = ((spec.flags & SPECIAL) && spec.base != 10); | 390 | int need_pfx = ((spec.flags & SPECIAL) && spec.base != 10); |
| @@ -422,12 +420,7 @@ char *number(char *buf, char *end, unsigned long long num, | |||
| 422 | /* generate full string in tmp[], in reverse order */ | 420 | /* generate full string in tmp[], in reverse order */ |
| 423 | i = 0; | 421 | i = 0; |
| 424 | if (num < spec.base) | 422 | if (num < spec.base) |
| 425 | tmp[i++] = digits[num] | locase; | 423 | tmp[i++] = hex_asc_upper[num] | locase; |
| 426 | /* Generic code, for any base: | ||
| 427 | else do { | ||
| 428 | tmp[i++] = (digits[do_div(num,base)] | locase); | ||
| 429 | } while (num != 0); | ||
| 430 | */ | ||
| 431 | else if (spec.base != 10) { /* 8 or 16 */ | 424 | else if (spec.base != 10) { /* 8 or 16 */ |
| 432 | int mask = spec.base - 1; | 425 | int mask = spec.base - 1; |
| 433 | int shift = 3; | 426 | int shift = 3; |
| @@ -435,7 +428,7 @@ char *number(char *buf, char *end, unsigned long long num, | |||
| 435 | if (spec.base == 16) | 428 | if (spec.base == 16) |
| 436 | shift = 4; | 429 | shift = 4; |
| 437 | do { | 430 | do { |
| 438 | tmp[i++] = (digits[((unsigned char)num) & mask] | locase); | 431 | tmp[i++] = (hex_asc_upper[((unsigned char)num) & mask] | locase); |
| 439 | num >>= shift; | 432 | num >>= shift; |
| 440 | } while (num); | 433 | } while (num); |
| 441 | } else { /* base 10 */ | 434 | } else { /* base 10 */ |
| @@ -447,7 +440,7 @@ char *number(char *buf, char *end, unsigned long long num, | |||
| 447 | spec.precision = i; | 440 | spec.precision = i; |
| 448 | /* leading space padding */ | 441 | /* leading space padding */ |
| 449 | spec.field_width -= spec.precision; | 442 | spec.field_width -= spec.precision; |
| 450 | if (!(spec.flags & (ZEROPAD+LEFT))) { | 443 | if (!(spec.flags & (ZEROPAD | LEFT))) { |
| 451 | while (--spec.field_width >= 0) { | 444 | while (--spec.field_width >= 0) { |
| 452 | if (buf < end) | 445 | if (buf < end) |
| 453 | *buf = ' '; | 446 | *buf = ' '; |
| @@ -475,7 +468,8 @@ char *number(char *buf, char *end, unsigned long long num, | |||
| 475 | } | 468 | } |
| 476 | /* zero or space padding */ | 469 | /* zero or space padding */ |
| 477 | if (!(spec.flags & LEFT)) { | 470 | if (!(spec.flags & LEFT)) { |
| 478 | char c = (spec.flags & ZEROPAD) ? '0' : ' '; | 471 | char c = ' ' + (spec.flags & ZEROPAD); |
| 472 | BUILD_BUG_ON(' ' + ZEROPAD != '0'); | ||
| 479 | while (--spec.field_width >= 0) { | 473 | while (--spec.field_width >= 0) { |
| 480 | if (buf < end) | 474 | if (buf < end) |
| 481 | *buf = c; | 475 | *buf = c; |
| @@ -783,11 +777,19 @@ char *hex_string(char *buf, char *end, u8 *addr, struct printf_spec spec, | |||
| 783 | if (spec.field_width > 0) | 777 | if (spec.field_width > 0) |
| 784 | len = min_t(int, spec.field_width, 64); | 778 | len = min_t(int, spec.field_width, 64); |
| 785 | 779 | ||
| 786 | for (i = 0; i < len && buf < end - 1; i++) { | 780 | for (i = 0; i < len; ++i) { |
| 787 | buf = hex_byte_pack(buf, addr[i]); | 781 | if (buf < end) |
| 782 | *buf = hex_asc_hi(addr[i]); | ||
| 783 | ++buf; | ||
| 784 | if (buf < end) | ||
| 785 | *buf = hex_asc_lo(addr[i]); | ||
| 786 | ++buf; | ||
| 788 | 787 | ||
| 789 | if (buf < end && separator && i != len - 1) | 788 | if (separator && i != len - 1) { |
| 790 | *buf++ = separator; | 789 | if (buf < end) |
| 790 | *buf = separator; | ||
| 791 | ++buf; | ||
| 792 | } | ||
| 791 | } | 793 | } |
| 792 | 794 | ||
| 793 | return buf; | 795 | return buf; |
| @@ -1233,8 +1235,12 @@ char *escaped_string(char *buf, char *end, u8 *addr, struct printf_spec spec, | |||
| 1233 | 1235 | ||
| 1234 | len = spec.field_width < 0 ? 1 : spec.field_width; | 1236 | len = spec.field_width < 0 ? 1 : spec.field_width; |
| 1235 | 1237 | ||
| 1236 | /* Ignore the error. We print as many characters as we can */ | 1238 | /* |
| 1237 | string_escape_mem(addr, len, &buf, end - buf, flags, NULL); | 1239 | * string_escape_mem() writes as many characters as it can to |
| 1240 | * the given buffer, and returns the total size of the output | ||
| 1241 | * had the buffer been big enough. | ||
| 1242 | */ | ||
| 1243 | buf += string_escape_mem(addr, len, buf, buf < end ? end - buf : 0, flags, NULL); | ||
| 1238 | 1244 | ||
| 1239 | return buf; | 1245 | return buf; |
| 1240 | } | 1246 | } |
| @@ -1322,6 +1328,30 @@ char *address_val(char *buf, char *end, const void *addr, | |||
| 1322 | return number(buf, end, num, spec); | 1328 | return number(buf, end, num, spec); |
| 1323 | } | 1329 | } |
| 1324 | 1330 | ||
| 1331 | static noinline_for_stack | ||
| 1332 | char *clock(char *buf, char *end, struct clk *clk, struct printf_spec spec, | ||
| 1333 | const char *fmt) | ||
| 1334 | { | ||
| 1335 | if (!IS_ENABLED(CONFIG_HAVE_CLK) || !clk) | ||
| 1336 | return string(buf, end, NULL, spec); | ||
| 1337 | |||
| 1338 | switch (fmt[1]) { | ||
| 1339 | case 'r': | ||
| 1340 | return number(buf, end, clk_get_rate(clk), spec); | ||
| 1341 | |||
| 1342 | case 'n': | ||
| 1343 | default: | ||
| 1344 | #ifdef CONFIG_COMMON_CLK | ||
| 1345 | return string(buf, end, __clk_get_name(clk), spec); | ||
| 1346 | #else | ||
| 1347 | spec.base = 16; | ||
| 1348 | spec.field_width = sizeof(unsigned long) * 2 + 2; | ||
| 1349 | spec.flags |= SPECIAL | SMALL | ZEROPAD; | ||
| 1350 | return number(buf, end, (unsigned long)clk, spec); | ||
| 1351 | #endif | ||
| 1352 | } | ||
| 1353 | } | ||
| 1354 | |||
| 1325 | int kptr_restrict __read_mostly; | 1355 | int kptr_restrict __read_mostly; |
| 1326 | 1356 | ||
| 1327 | /* | 1357 | /* |
| @@ -1404,6 +1434,11 @@ int kptr_restrict __read_mostly; | |||
| 1404 | * (default assumed to be phys_addr_t, passed by reference) | 1434 | * (default assumed to be phys_addr_t, passed by reference) |
| 1405 | * - 'd[234]' For a dentry name (optionally 2-4 last components) | 1435 | * - 'd[234]' For a dentry name (optionally 2-4 last components) |
| 1406 | * - 'D[234]' Same as 'd' but for a struct file | 1436 | * - 'D[234]' Same as 'd' but for a struct file |
| 1437 | * - 'C' For a clock, it prints the name (Common Clock Framework) or address | ||
| 1438 | * (legacy clock framework) of the clock | ||
| 1439 | * - 'Cn' For a clock, it prints the name (Common Clock Framework) or address | ||
| 1440 | * (legacy clock framework) of the clock | ||
| 1441 | * - 'Cr' For a clock, it prints the current rate of the clock | ||
| 1407 | * | 1442 | * |
| 1408 | * Note: The difference between 'S' and 'F' is that on ia64 and ppc64 | 1443 | * Note: The difference between 'S' and 'F' is that on ia64 and ppc64 |
| 1409 | * function pointers are really function descriptors, which contain a | 1444 | * function pointers are really function descriptors, which contain a |
| @@ -1548,6 +1583,8 @@ char *pointer(const char *fmt, char *buf, char *end, void *ptr, | |||
| 1548 | return address_val(buf, end, ptr, spec, fmt); | 1583 | return address_val(buf, end, ptr, spec, fmt); |
| 1549 | case 'd': | 1584 | case 'd': |
| 1550 | return dentry_name(buf, end, ptr, spec, fmt); | 1585 | return dentry_name(buf, end, ptr, spec, fmt); |
| 1586 | case 'C': | ||
| 1587 | return clock(buf, end, ptr, spec, fmt); | ||
| 1551 | case 'D': | 1588 | case 'D': |
| 1552 | return dentry_name(buf, end, | 1589 | return dentry_name(buf, end, |
| 1553 | ((const struct file *)ptr)->f_path.dentry, | 1590 | ((const struct file *)ptr)->f_path.dentry, |
| @@ -1738,29 +1775,21 @@ qualifier: | |||
| 1738 | if (spec->qualifier == 'L') | 1775 | if (spec->qualifier == 'L') |
| 1739 | spec->type = FORMAT_TYPE_LONG_LONG; | 1776 | spec->type = FORMAT_TYPE_LONG_LONG; |
| 1740 | else if (spec->qualifier == 'l') { | 1777 | else if (spec->qualifier == 'l') { |
| 1741 | if (spec->flags & SIGN) | 1778 | BUILD_BUG_ON(FORMAT_TYPE_ULONG + SIGN != FORMAT_TYPE_LONG); |
| 1742 | spec->type = FORMAT_TYPE_LONG; | 1779 | spec->type = FORMAT_TYPE_ULONG + (spec->flags & SIGN); |
| 1743 | else | ||
| 1744 | spec->type = FORMAT_TYPE_ULONG; | ||
| 1745 | } else if (_tolower(spec->qualifier) == 'z') { | 1780 | } else if (_tolower(spec->qualifier) == 'z') { |
| 1746 | spec->type = FORMAT_TYPE_SIZE_T; | 1781 | spec->type = FORMAT_TYPE_SIZE_T; |
| 1747 | } else if (spec->qualifier == 't') { | 1782 | } else if (spec->qualifier == 't') { |
| 1748 | spec->type = FORMAT_TYPE_PTRDIFF; | 1783 | spec->type = FORMAT_TYPE_PTRDIFF; |
| 1749 | } else if (spec->qualifier == 'H') { | 1784 | } else if (spec->qualifier == 'H') { |
| 1750 | if (spec->flags & SIGN) | 1785 | BUILD_BUG_ON(FORMAT_TYPE_UBYTE + SIGN != FORMAT_TYPE_BYTE); |
| 1751 | spec->type = FORMAT_TYPE_BYTE; | 1786 | spec->type = FORMAT_TYPE_UBYTE + (spec->flags & SIGN); |
| 1752 | else | ||
| 1753 | spec->type = FORMAT_TYPE_UBYTE; | ||
| 1754 | } else if (spec->qualifier == 'h') { | 1787 | } else if (spec->qualifier == 'h') { |
| 1755 | if (spec->flags & SIGN) | 1788 | BUILD_BUG_ON(FORMAT_TYPE_USHORT + SIGN != FORMAT_TYPE_SHORT); |
| 1756 | spec->type = FORMAT_TYPE_SHORT; | 1789 | spec->type = FORMAT_TYPE_USHORT + (spec->flags & SIGN); |
| 1757 | else | ||
| 1758 | spec->type = FORMAT_TYPE_USHORT; | ||
| 1759 | } else { | 1790 | } else { |
| 1760 | if (spec->flags & SIGN) | 1791 | BUILD_BUG_ON(FORMAT_TYPE_UINT + SIGN != FORMAT_TYPE_INT); |
| 1761 | spec->type = FORMAT_TYPE_INT; | 1792 | spec->type = FORMAT_TYPE_UINT + (spec->flags & SIGN); |
| 1762 | else | ||
| 1763 | spec->type = FORMAT_TYPE_UINT; | ||
| 1764 | } | 1793 | } |
| 1765 | 1794 | ||
| 1766 | return ++fmt - start; | 1795 | return ++fmt - start; |
| @@ -1800,6 +1829,11 @@ qualifier: | |||
| 1800 | * %*pE[achnops] print an escaped buffer | 1829 | * %*pE[achnops] print an escaped buffer |
| 1801 | * %*ph[CDN] a variable-length hex string with a separator (supports up to 64 | 1830 | * %*ph[CDN] a variable-length hex string with a separator (supports up to 64 |
| 1802 | * bytes of the input) | 1831 | * bytes of the input) |
| 1832 | * %pC output the name (Common Clock Framework) or address (legacy clock | ||
| 1833 | * framework) of a clock | ||
| 1834 | * %pCn output the name (Common Clock Framework) or address (legacy clock | ||
| 1835 | * framework) of a clock | ||
| 1836 | * %pCr output the current rate of a clock | ||
| 1803 | * %n is ignored | 1837 | * %n is ignored |
| 1804 | * | 1838 | * |
| 1805 | * ** Please update Documentation/printk-formats.txt when making changes ** | 1839 | * ** Please update Documentation/printk-formats.txt when making changes ** |
